
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_Hans">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>翻译 &#8212; Django 3.2.11.dev 文档</title>
    <link rel="stylesheet" href="../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../_static/language_data.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="本地格式化" href="formatting.html" />
    <link rel="prev" title="国际化和本地化" href="index.html" />



 
<script src="../../templatebuiltins.js"></script>
<script>
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../../ref/templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../index.html">Django 3.2.11.dev 文档</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../index.html">Home</a>  |
        <a title="Table of contents" href="../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../genindex.html">Index</a>  |
        <a title="Module index" href="../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="index.html" title="国际化和本地化">previous</a>
     |
    <a href="../index.html" title="使用 Django" accesskey="U">up</a>
   |
    <a href="formatting.html" title="本地格式化">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="topics-i18n-translation">
            
  <div class="section" id="s-translation">
<span id="translation"></span><h1>翻译<a class="headerlink" href="#translation" title="永久链接至标题">¶</a></h1>
<div class="section" id="s-overview">
<span id="overview"></span><h2>概况<a class="headerlink" href="#overview" title="永久链接至标题">¶</a></h2>
<p>为了使 Django 项目可以翻译，你需要在 Python 代码和模板中添加少量钩子。这些钩子被成为 <a class="reference internal" href="index.html#term-translation-string"><span class="xref std std-term">translation strings</span></a> 。它们告知Django：如果在终端用户语言里，这个文本有对应的翻译，那么应该使用翻译。标记字符串是你的职责，系统只会翻译它知道的字符串。</p>
<p>然后 Django 提供工具将翻译字符串提取到 <a class="reference internal" href="index.html#term-message-file"><span class="xref std std-term">message file</span></a> 中。这个文件让翻译者方便地提供翻译字符串。一旦翻译者填写了 message file ，就必须编译它。这个过程依赖 GNU gettext 工具集。</p>
<p>完成后，Django 会根据用户的语言偏好，使用每种可用语言对网页进行即时翻译。</p>
<p>Django 的国际化钩子默认是开启的，这意味着在框架的某些位置存在一些 i18n 相关的开销。如果你不使用国际化，你应该在配置文件里设置 <a class="reference internal" href="../../ref/settings.html#std:setting-USE_I18N"><code class="xref std std-setting docutils literal notranslate"><span class="pre">USE_I18N</span> <span class="pre">=</span> <span class="pre">False</span></code></a> 。然后 Django 将进行优化，以免加载国际化机制。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">还有一个有关 <a class="reference internal" href="../../ref/settings.html#std:setting-USE_L10N"><code class="xref std std-setting docutils literal notranslate"><span class="pre">USE_L10N</span></code></a> 的设置，用来控制 Django 是否应该实现格式本地化。查看 <a class="reference internal" href="formatting.html"><span class="doc">本地格式化</span></a> 获取更多细节。</p>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">确保你的项目已经激活了翻译（最快的办法是检查 <a class="reference internal" href="../../ref/settings.html#std:setting-MIDDLEWARE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">MIDDLEWARE</span></code></a> 是否包含 <a class="reference internal" href="../../ref/middleware.html#django.middleware.locale.LocaleMiddleware" title="django.middleware.locale.LocaleMiddleware"><code class="xref py py-mod docutils literal notranslate"><span class="pre">django.middleware.locale.LocaleMiddleware</span></code></a> ）。如果还没有激活，请查看“ Django 如何发现语言偏好（ <a class="reference internal" href="#how-django-discovers-language-preference"><span class="std std-ref">Django 如何发现语言偏好</span></a> ）”。</p>
</div>
</div>
<div class="section" id="s-internationalization-in-python-code">
<span id="internationalization-in-python-code"></span><h2>在 Python 代码中进行国际化<a class="headerlink" href="#internationalization-in-python-code" title="永久链接至标题">¶</a></h2>
<div class="section" id="s-standard-translation">
<span id="standard-translation"></span><h3>标准翻译<a class="headerlink" href="#standard-translation" title="永久链接至标题">¶</a></h3>
<p>使用函数 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext" title="django.utils.translation.gettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext()</span></code></a> 来指定翻译字符串。按照惯例，将其作为下划线( _ )导入，以保存输入。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>Python 标准库 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 模块在全局命名空间里安装了 <code class="docutils literal notranslate"><span class="pre">_()</span></code> 。在 Django 里，我们没有遵循这个做法，出于下面两个原因：</p>
<ol class="last arabic simple">
<li>有时，对于特定文件，你应该使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_lazy" title="django.utils.translation.gettext_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext_lazy()</span></code></a> 作为默认翻译方法。如果全局命名空间里没有 <code class="docutils literal notranslate"><span class="pre">_()</span></code> ，开发者必须考虑哪个是最合适的翻译函数。</li>
<li>下划线(&quot;_&quot;) 用于表示在 Python 的交互式终端和 doctest 测试中 &quot;上一个结果&quot; 。安装全局 <code class="docutils literal notranslate"><span class="pre">_()</span></code> 函数会引发冲突。导入 <code class="docutils literal notranslate"><span class="pre">gettext()</span></code> 替换 <code class="docutils literal notranslate"><span class="pre">_()</span></code> 可以避免这个问题。</li>
</ol>
</div>
<div class="admonition-what-functions-may-be-aliased-as admonition">
<p class="first admonition-title">哪些函数能以 <code class="docutils literal notranslate"><span class="pre">_</span></code> 为别名？</p>
<p>由于 <code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 的工作方式，只有带有单一字符串参数的函数才能当做 <code class="docutils literal notranslate"><span class="pre">_</span></code> 引入：</p>
<ul class="last simple">
<li><a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext" title="django.utils.translation.gettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext()</span></code></a></li>
<li><a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_lazy" title="django.utils.translation.gettext_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext_lazy()</span></code></a></li>
</ul>
</div>
<p>在这个例子里，文本  <code class="docutils literal notranslate"><span class="pre">&quot;Welcome</span> <span class="pre">to</span> <span class="pre">my</span> <span class="pre">site.&quot;</span></code>&nbsp; 被标记为翻译字符串：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">&quot;Welcome to my site.&quot;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
</pre></div>
</div>
<p>代码里可以不使用别名。这个例子与上一个例子等同：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext</span>

<span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">gettext</span><span class="p">(</span><span class="s2">&quot;Welcome to my site.&quot;</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
</pre></div>
</div>
<p>翻译适用于计算值。这个例子与前面两个例子等同：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">words</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;Welcome&#39;</span><span class="p">,</span> <span class="s1">&#39;to&#39;</span><span class="p">,</span> <span class="s1">&#39;my&#39;</span><span class="p">,</span> <span class="s1">&#39;site.&#39;</span><span class="p">]</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
</pre></div>
</div>
<p>翻译适用于变量。同样，这个例子和上面的等同：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">sentence</span> <span class="o">=</span> <span class="s1">&#39;Welcome to my site.&#39;</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="n">sentence</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
</pre></div>
</div>
<p>(像上述两个例子那样，使用变量或计算值的警告是： Django 的翻译字符检测实用程序 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> 不能找到这些字符串。更多细节在稍后的  <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a>  介绍。)</p>
<p>传递到 <code class="docutils literal notranslate"><span class="pre">_()</span></code> or <code class="docutils literal notranslate"><span class="pre">gettext()</span></code>&nbsp; 的字符串可以使用占位符，这是 Python 标准命名字符串插值语法指定的。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;Today is </span><span class="si">%(month)s</span><span class="s1"> </span><span class="si">%(day)s</span><span class="s1">.&#39;</span><span class="p">)</span> <span class="o">%</span> <span class="p">{</span><span class="s1">&#39;month&#39;</span><span class="p">:</span> <span class="n">m</span><span class="p">,</span> <span class="s1">&#39;day&#39;</span><span class="p">:</span> <span class="n">d</span><span class="p">}</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
</pre></div>
</div>
<p>这是技巧使得特定语言翻译可以重新排序占位符字段。比如，一条英文翻译可能是 <code class="docutils literal notranslate"><span class="pre">&quot;Today</span> <span class="pre">is</span> <span class="pre">November</span> <span class="pre">26.&quot;</span></code> ，而对于西班牙翻译可能就是  <code class="docutils literal notranslate"><span class="pre">&quot;Hoy</span> <span class="pre">es</span> <span class="pre">26</span> <span class="pre">de</span> <span class="pre">noviembre.&quot;</span></code> ——其中月份和日期占位符互相交换。</p>
<p>所以，当你有多个参数的时候，你应该使用命名字符串插值（比如 %(day)s ）而不是位置插值（比如 %s 或 %d ）。如果你使用位置插值，翻译时就不会对占位符字段重新排序。</p>
<p>因为字符串提取由 <code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 命令行完成，Django 仅支持由 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 支持的语法。特别是，<code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 尚未支持 Python <a class="reference external" href="https://docs.python.org/3/reference/lexical_analysis.html#f-strings" title="(在 Python v3.10)"><span class="xref std std-ref">f-strings</span></a> ，而 JavaScript 模板字符串需要 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 0.21+ 。</p>
</div>
<div class="section" id="s-comments-for-translators">
<span id="s-translator-comments"></span><span id="comments-for-translators"></span><span id="translator-comments"></span><h3>为翻译者提供注释<a class="headerlink" href="#comments-for-translators" title="永久链接至标题">¶</a></h3>
<p>如果你想为翻译者提供一些翻译字段的提示，你可以添加以 <code class="docutils literal notranslate"><span class="pre">Translators</span></code> 为前缀的注释。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">my_view</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="c1"># Translators: This message appears on the home page only</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">gettext</span><span class="p">(</span><span class="s2">&quot;Welcome to my site.&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>这个注释将出现在 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件中与所翻译词条相关的词条下方，并且也应该由大部分翻译工具显示。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>为了完整起见，这是 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件的相应片段：</p>
<div class="last highlight-po notranslate"><div class="highlight"><pre><span></span><span class="c1">#. Translators: This message appears on the home page only</span>
<span class="c1"># path/to/python/file.py:123</span>
<span class="nv">msgid</span> <span class="s">&quot;Welcome to my site.&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>
</pre></div>
</div>
</div>
<p>这个办法在模板里也同样适用。查看 <a class="reference internal" href="#translator-comments-in-templates"><span class="std std-ref">模板内对翻译的注释</span></a> 来获取更多详情。</p>
</div>
<div class="section" id="s-marking-strings-as-no-op">
<span id="marking-strings-as-no-op"></span><h3>标记不用翻译的字符<a class="headerlink" href="#marking-strings-as-no-op" title="永久链接至标题">¶</a></h3>
<p>使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_noop" title="django.utils.translation.gettext_noop"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.gettext_noop()</span></code></a> 来将字符串标记不用翻译的翻译字符串。这个字符会稍后使用变量来翻译。</p>
<p>使用该方法的场景是：如果你有一个常量字符串，该字符串以源语言存储，它们通过系统或用户进行交换（比如数据库里的字符串），但应该最后可能的时间点进行翻译，比如当字符串展示给用户时。</p>
</div>
<div class="section" id="s-pluralization">
<span id="pluralization"></span><h3>多元化<a class="headerlink" href="#pluralization" title="永久链接至标题">¶</a></h3>
<p>使用  <a class="reference internal" href="../../ref/utils.html#django.utils.translation.ngettext" title="django.utils.translation.ngettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.ngettext()</span></code></a>  函数指定多元化信息。</p>
<p><code class="docutils literal notranslate"><span class="pre">ngettext()</span></code> 带有三个参数：单数翻译字符串，复数翻译字符串和一些对象。</p>
<p>当你需要 Django 应用本地化为复数形式的数量和复杂度大于英语中使用的两种形式的语言时，该函数非常有用。（'object' 表示单数，'objects' 表示  <code class="docutils literal notranslate"><span class="pre">count</span></code>  不同于1时的所有情况，不论其值如何）</p>
<p>例如:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">ngettext</span>

<span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
    <span class="n">page</span> <span class="o">=</span> <span class="n">ngettext</span><span class="p">(</span>
        <span class="s1">&#39;there is </span><span class="si">%(count)d</span><span class="s1"> object&#39;</span><span class="p">,</span>
        <span class="s1">&#39;there are </span><span class="si">%(count)d</span><span class="s1"> objects&#39;</span><span class="p">,</span>
        <span class="n">count</span><span class="p">,</span>
    <span class="p">)</span> <span class="o">%</span> <span class="p">{</span>
        <span class="s1">&#39;count&#39;</span><span class="p">:</span> <span class="n">count</span><span class="p">,</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="n">page</span><span class="p">)</span>
</pre></div>
</div>
<p>在这个例子里，对象的数量作为 count 变量传递给翻译语言。</p>
<p>要注意复数形式是复杂的，并且在每种语言中工作方式不同。比较 count 和 1 并不总是正确的规则。该代码看着很复杂，但会对某些语言产生不正确的结果：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">ngettext</span>
<span class="kn">from</span> <span class="nn">myapp.models</span> <span class="kn">import</span> <span class="n">Report</span>

<span class="n">count</span> <span class="o">=</span> <span class="n">Report</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">count</span><span class="p">()</span>
<span class="k">if</span> <span class="n">count</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">Report</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">verbose_name</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">Report</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">verbose_name_plural</span>

<span class="n">text</span> <span class="o">=</span> <span class="n">ngettext</span><span class="p">(</span>
    <span class="s1">&#39;There is </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1"> available.&#39;</span><span class="p">,</span>
    <span class="s1">&#39;There are </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1"> available.&#39;</span><span class="p">,</span>
    <span class="n">count</span><span class="p">,</span>
<span class="p">)</span> <span class="o">%</span> <span class="p">{</span>
    <span class="s1">&#39;count&#39;</span><span class="p">:</span> <span class="n">count</span><span class="p">,</span>
    <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">name</span>
<span class="p">}</span>
</pre></div>
</div>
<p>不要尝试实现自定义的单数或复数逻辑，它会出错的。像在这种例子中，请考虑以下内容：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">text</span> <span class="o">=</span> <span class="n">ngettext</span><span class="p">(</span>
    <span class="s1">&#39;There is </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1"> object available.&#39;</span><span class="p">,</span>
    <span class="s1">&#39;There are </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1"> objects available.&#39;</span><span class="p">,</span>
    <span class="n">count</span><span class="p">,</span>
<span class="p">)</span> <span class="o">%</span> <span class="p">{</span>
    <span class="s1">&#39;count&#39;</span><span class="p">:</span> <span class="n">count</span><span class="p">,</span>
    <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">Report</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="admonition note" id="pluralization-var-notes">
<p class="first admonition-title">注解</p>
<p>当使用 <code class="docutils literal notranslate"><span class="pre">ngettext()</span></code> 时，要确保为每一个变量使用一个名称。上面的例子中，请注意我们在两个翻译字符串中如何使用 <code class="docutils literal notranslate"><span class="pre">name</span></code> Python 变量。该例子除了上面提到的错误外，还会遇到下面的问题：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">text</span> <span class="o">=</span> <span class="n">ngettext</span><span class="p">(</span>
    <span class="s1">&#39;There is </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1"> available.&#39;</span><span class="p">,</span>
    <span class="s1">&#39;There are </span><span class="si">%(count)d</span><span class="s1"> </span><span class="si">%(plural_name)s</span><span class="s1"> available.&#39;</span><span class="p">,</span>
    <span class="n">count</span><span class="p">,</span>
<span class="p">)</span> <span class="o">%</span> <span class="p">{</span>
    <span class="s1">&#39;count&#39;</span><span class="p">:</span> <span class="n">Report</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">count</span><span class="p">(),</span>
    <span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="n">Report</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">verbose_name</span><span class="p">,</span>
    <span class="s1">&#39;plural_name&#39;</span><span class="p">:</span> <span class="n">Report</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">verbose_name_plural</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>当正在运行 <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span></code></a> 时会遇到错误：</p>
<div class="last highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="nb">format</span> <span class="n">specification</span> <span class="k">for</span> <span class="n">argument</span> <span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="k">as</span> <span class="ow">in</span> <span class="s1">&#39;msgstr[0]&#39;</span><span class="p">,</span> <span class="n">doesn</span><span class="s1">&#39;t exist in &#39;</span><span class="n">msgid</span><span class="s1">&#39;</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-contextual-markers">
<span id="s-id1"></span><span id="contextual-markers"></span><span id="id1"></span><h3>上下文标记<a class="headerlink" href="#contextual-markers" title="永久链接至标题">¶</a></h3>
<p>一些词组有很多不同含义，比如 <code class="docutils literal notranslate"><span class="pre">&quot;May&quot;</span></code> ，它指五月或者表示一个动词。为了使翻译者在不同上下文中正确翻译这些词组，可以使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.pgettext" title="django.utils.translation.pgettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.pgettext()</span></code></a> 函数，或者如果字符串需要复数形式的话，可以使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.npgettext" title="django.utils.translation.npgettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.npgettext()</span></code></a> 函数。两者都使用上下文字符串作为第一个变量。</p>
<p>在生成的 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件中，字符串将会频繁出现，因为相同字符串 ( 上下文将在 <code class="docutils literal notranslate"><span class="pre">msgctxt</span></code> 行上显示) 有不同的上下文标记，所以允许翻译者为每个字符串给出不同翻译。</p>
<p>例如:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">pgettext</span>

<span class="n">month</span> <span class="o">=</span> <span class="n">pgettext</span><span class="p">(</span><span class="s2">&quot;month name&quot;</span><span class="p">,</span> <span class="s2">&quot;May&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>或者：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">pgettext_lazy</span>

<span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">help_text</span><span class="o">=</span><span class="n">pgettext_lazy</span><span class="p">(</span>
        <span class="s1">&#39;help text for MyThing model&#39;</span><span class="p">,</span> <span class="s1">&#39;This is the help text&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>将以下方形式出现在 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件中：</p>
<div class="highlight-po notranslate"><div class="highlight"><pre><span></span><span class="nv">msgctxt</span> <span class="s">&quot;month name&quot;</span>
<span class="nv">msgid</span> <span class="s">&quot;May&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>
</pre></div>
</div>
<p>上下文标记也由 <a class="reference internal" href="#std:templatetag-translate"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">translate</span></code></a> 和 <a class="reference internal" href="#std:templatetag-blocktranslate"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">blocktranslate</span></code></a> 模板标签支持。</p>
</div>
<div class="section" id="s-lazy-translation">
<span id="s-lazy-translations"></span><span id="lazy-translation"></span><span id="lazy-translations"></span><h3>惰性翻译<a class="headerlink" href="#lazy-translation" title="永久链接至标题">¶</a></h3>
<p>当访问值而不是调用它们时，使用 <a class="reference internal" href="../../ref/utils.html#module-django.utils.translation" title="django.utils.translation: Internationalization support."><code class="xref py py-mod docutils literal notranslate"><span class="pre">django.utils.translation</span></code></a> 中翻译函数的惰性版本 (在名称中加入 <code class="docutils literal notranslate"><span class="pre">lazy</span></code> 前缀来识别) 来延迟翻译字符串。</p>
<p>这些函数存储对字符串的惰性引用 —— 并非真实的翻译。当在字符串上下文里使用字符串时，才会翻译。比如模板渲染。</p>
<p>当对这些函数的调用位于模块加载时执行的代码路径中时，这一点非常重要。</p>
<p>在定义模型、表单和模型表单的时候，很容易遇见这种情况，因为 Django 已经实现了这些，所以它们的字段实际是类级别的属性。因此，请确保以下情况下使用惰性翻译：</p>
<div class="section" id="s-model-fields-and-relationships-verbose-name-and-help-text-option-values">
<span id="model-fields-and-relationships-verbose-name-and-help-text-option-values"></span><h4>模型字段和相关的 <code class="docutils literal notranslate"><span class="pre">verbose_name</span></code> 与 <code class="docutils literal notranslate"><span class="pre">help_text</span></code> 选项值<a class="headerlink" href="#model-fields-and-relationships-verbose-name-and-help-text-option-values" title="永久链接至标题">¶</a></h4>
<p>比如下面这个模型，为了翻译其中 <em>name</em> 字段的帮助提示，可以这么做：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">help_text</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;This is the help text&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>你可以通过使用 <a class="reference internal" href="../../ref/models/options.html#django.db.models.Options.verbose_name" title="django.db.models.Options.verbose_name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">verbose_name</span></code></a> 选项来将  <a class="reference internal" href="../../ref/models/fields.html#django.db.models.ForeignKey" title="django.db.models.ForeignKey"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForeignKey</span></code></a>, <a class="reference internal" href="../../ref/models/fields.html#django.db.models.ManyToManyField" title="django.db.models.ManyToManyField"><code class="xref py py-class docutils literal notranslate"><span class="pre">ManyToManyField</span></code></a> 或 <a class="reference internal" href="../../ref/models/fields.html#django.db.models.OneToOneField" title="django.db.models.OneToOneField"><code class="xref py py-class docutils literal notranslate"><span class="pre">OneToOneField</span></code></a> 关系标记为可翻译：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">kind</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span>
        <span class="n">ThingKind</span><span class="p">,</span>
        <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">,</span>
        <span class="n">related_name</span><span class="o">=</span><span class="s1">&#39;kinds&#39;</span><span class="p">,</span>
        <span class="n">verbose_name</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;kind&#39;</span><span class="p">),</span>
    <span class="p">)</span>
</pre></div>
</div>
<p>就像你在 <a class="reference internal" href="../../ref/models/options.html#django.db.models.Options.verbose_name" title="django.db.models.Options.verbose_name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">verbose_name</span></code></a> 中所做的那样，你应该为关系提供一个小写的详细名称文本，因为 Django 会在需要时自动为其命名。</p>
</div>
<div class="section" id="s-model-verbose-names-values">
<span id="model-verbose-names-values"></span><h4>模型详细名称的值<a class="headerlink" href="#model-verbose-names-values" title="永久链接至标题">¶</a></h4>
<p>建议始终提供显式的 <a class="reference internal" href="../../ref/models/options.html#django.db.models.Options.verbose_name" title="django.db.models.Options.verbose_name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">verbose_name</span></code></a> 和  <a class="reference internal" href="../../ref/models/options.html#django.db.models.Options.verbose_name_plural" title="django.db.models.Options.verbose_name_plural"><code class="xref py py-attr docutils literal notranslate"><span class="pre">verbose_name_plural</span></code></a> 选项，而不是依赖 Django 查看模型的类名来确定以英文为主而且有点简单的详细名称：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">),</span> <span class="n">help_text</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;This is the help text&#39;</span><span class="p">))</span>

    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">verbose_name</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;my thing&#39;</span><span class="p">)</span>
        <span class="n">verbose_name_plural</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;my things&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-model-methods-description-argument-to-the-display-decorator">
<span id="model-methods-description-argument-to-the-display-decorator"></span><h4>Model methods <code class="docutils literal notranslate"><span class="pre">description</span></code> argument to the <code class="docutils literal notranslate"><span class="pre">&#64;display</span></code> decorator<a class="headerlink" href="#model-methods-description-argument-to-the-display-decorator" title="永久链接至标题">¶</a></h4>
<p>For model methods, you can provide translations to Django and the admin site
with the <code class="docutils literal notranslate"><span class="pre">description</span></code> argument to the <a class="reference internal" href="../../ref/contrib/admin/index.html#django.contrib.admin.display" title="django.contrib.admin.display"><code class="xref py py-func docutils literal notranslate"><span class="pre">display()</span></code></a>
decorator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.contrib</span> <span class="kn">import</span> <span class="n">admin</span>
<span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">kind</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span>
        <span class="n">ThingKind</span><span class="p">,</span>
        <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">CASCADE</span><span class="p">,</span>
        <span class="n">related_name</span><span class="o">=</span><span class="s1">&#39;kinds&#39;</span><span class="p">,</span>
        <span class="n">verbose_name</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;kind&#39;</span><span class="p">),</span>
    <span class="p">)</span>

    <span class="nd">@admin</span><span class="o">.</span><span class="n">display</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;Is it a mouse?&#39;</span><span class="p">))</span>
    <span class="k">def</span> <span class="nf">is_mouse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">kind</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">MOUSE_TYPE</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-working-with-lazy-translation-objects">
<span id="working-with-lazy-translation-objects"></span><h3>使用惰性翻译对象<a class="headerlink" href="#working-with-lazy-translation-objects" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">gettext_lazy()</span></code> 调用的结果可以在其他 Django 代码使用字符串( <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(在 Python v3.10)"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> 对象)的任何地方使用，但它可能不适用于任何 Python 代码。比如，下面这种情况就不行，因为 <a class="reference external" href="https://pypi.org/project/requests/">requests</a> 库不会处理 <code class="docutils literal notranslate"><span class="pre">gettext_lazy</span></code> 对象：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">body</span> <span class="o">=</span> <span class="n">gettext_lazy</span><span class="p">(</span><span class="s2">&quot;I </span><span class="se">\u2764</span><span class="s2"> Django&quot;</span><span class="p">)</span>  <span class="c1"># (Unicode :heart:)</span>
<span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s1">&#39;https://example.com/send&#39;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;body&#39;</span><span class="p">:</span> <span class="n">body</span><span class="p">})</span>
</pre></div>
</div>
<p>要想避免这些问题，你可以在文本字符传递给非 Django 代码之前，将  <code class="docutils literal notranslate"><span class="pre">gettext_lazy()</span></code> 对象转换为文本字符。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s1">&#39;https://example.com/send&#39;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;body&#39;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">body</span><span class="p">)})</span>
</pre></div>
</div>
<p>如果你觉得 <code class="docutils literal notranslate"><span class="pre">gettext_lazy</span></code> 这个名字有点长，你可以定义它的别名为下划线 <code class="docutils literal notranslate"><span class="pre">_</span></code> ，像这样：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">MyThing</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">help_text</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;This is the help text&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>在模型和工具函数里使用 <code class="docutils literal notranslate"><span class="pre">gettext_lazy()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">ngettext_lazy()</span></code> 来标记字符串是个常用方法。但在代码的其他地方使用这些对象时，你要确保它们不会被不小心转化为字符串，因为它们要尽量晚一些被转换（以便正确的语言环境生效）。这需要使用下面所描述的帮助函数。</p>
<div class="section" id="s-lazy-translations-and-plural">
<span id="s-lazy-plural-translations"></span><span id="lazy-translations-and-plural"></span><span id="lazy-plural-translations"></span><h4>惰性翻译与复数<a class="headerlink" href="#lazy-translations-and-plural" title="永久链接至标题">¶</a></h4>
<p>当为复数字符串 (<code class="docutils literal notranslate"><span class="pre">n[p]gettext_lazy</span></code>) 使用惰性翻译时，通常不知道字符串定义时  <code class="docutils literal notranslate"><span class="pre">number</span></code> 参数值。因此，你可以传递一个关键字名称来作为  <code class="docutils literal notranslate"><span class="pre">number</span></code> 参数而不是整数。然后，在插值期间，会在字典里查找 <code class="docutils literal notranslate"><span class="pre">number</span></code>。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">forms</span>
<span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="kn">import</span> <span class="n">ValidationError</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">ngettext_lazy</span>

<span class="k">class</span> <span class="nc">MyForm</span><span class="p">(</span><span class="n">forms</span><span class="o">.</span><span class="n">Form</span><span class="p">):</span>
    <span class="n">error_message</span> <span class="o">=</span> <span class="n">ngettext_lazy</span><span class="p">(</span><span class="s2">&quot;You only provided </span><span class="si">%(num)d</span><span class="s2"> argument&quot;</span><span class="p">,</span>
        <span class="s2">&quot;You only provided </span><span class="si">%(num)d</span><span class="s2"> arguments&quot;</span><span class="p">,</span> <span class="s1">&#39;num&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># ...</span>
        <span class="k">if</span> <span class="n">error</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">error_message</span> <span class="o">%</span> <span class="p">{</span><span class="s1">&#39;num&#39;</span><span class="p">:</span> <span class="n">number</span><span class="p">})</span>
</pre></div>
</div>
<p>如果字符串恰好包含一个未命名的占位符，你可以直接插入 <code class="docutils literal notranslate"><span class="pre">number</span></code> 参数：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyForm</span><span class="p">(</span><span class="n">forms</span><span class="o">.</span><span class="n">Form</span><span class="p">):</span>
    <span class="n">error_message</span> <span class="o">=</span> <span class="n">ngettext_lazy</span><span class="p">(</span>
        <span class="s2">&quot;You provided </span><span class="si">%d</span><span class="s2"> argument&quot;</span><span class="p">,</span>
        <span class="s2">&quot;You provided </span><span class="si">%d</span><span class="s2"> arguments&quot;</span><span class="p">,</span>
    <span class="p">)</span>

    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># ...</span>
        <span class="k">if</span> <span class="n">error</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">error_message</span> <span class="o">%</span> <span class="n">number</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-formatting-strings-format-lazy">
<span id="formatting-strings-format-lazy"></span><h4>格式化字符串：<code class="docutils literal notranslate"><span class="pre">format_lazy()</span></code><a class="headerlink" href="#formatting-strings-format-lazy" title="永久链接至标题">¶</a></h4>
<p>当 <code class="docutils literal notranslate"><span class="pre">format_string</span></code> 或 <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str.format" title="(在 Python v3.10)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.format()</span></code></a> 的任何参数包含惰性转换对象时，Python的 <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str.format" title="(在 Python v3.10)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.format()</span></code></a> 方法将不起作用。相反，你可以使用 <a class="reference internal" href="../../ref/utils.html#django.utils.text.format_lazy" title="django.utils.text.format_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.text.format_lazy()</span></code></a> ，它会创建一个仅当结果包含在字符串里时会才运行 <code class="docutils literal notranslate"><span class="pre">str.format()</span></code> 的惰性对象。比如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.text</span> <span class="kn">import</span> <span class="n">format_lazy</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span>
<span class="o">...</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">gettext_lazy</span><span class="p">(</span><span class="s1">&#39;John Lennon&#39;</span><span class="p">)</span>
<span class="n">instrument</span> <span class="o">=</span> <span class="n">gettext_lazy</span><span class="p">(</span><span class="s1">&#39;guitar&#39;</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">format_lazy</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">{name}</span><span class="s1">: </span><span class="si">{instrument}</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">,</span> <span class="n">instrument</span><span class="o">=</span><span class="n">instrument</span><span class="p">)</span>
</pre></div>
</div>
<p>在这种情况下，在 <code class="docutils literal notranslate"><span class="pre">result</span></code> 中的惰性翻译仅在字符串(通常在模板渲染时间)里使用 <code class="docutils literal notranslate"><span class="pre">result</span></code> 时才会被转换成字符串。</p>
</div>
<div class="section" id="s-other-uses-of-lazy-in-delayed-translations">
<span id="other-uses-of-lazy-in-delayed-translations"></span><h4>延迟翻译中惰性(lazy)的其他用法<a class="headerlink" href="#other-uses-of-lazy-in-delayed-translations" title="永久链接至标题">¶</a></h4>
<p>对于“你想延迟翻译，但不得不传递要翻译的字符串作为参数到其他函数”的情况，你可以在惰性调用中包装这个函数。比如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.functional</span> <span class="kn">import</span> <span class="n">lazy</span>
<span class="kn">from</span> <span class="nn">django.utils.safestring</span> <span class="kn">import</span> <span class="n">mark_safe</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="n">mark_safe_lazy</span> <span class="o">=</span> <span class="n">lazy</span><span class="p">(</span><span class="n">mark_safe</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span>
</pre></div>
</div>
<p>然后：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">lazy_string</span> <span class="o">=</span> <span class="n">mark_safe_lazy</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s2">&quot;&lt;p&gt;My &lt;strong&gt;string!&lt;/strong&gt;&lt;/p&gt;&quot;</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-localized-names-of-languages">
<span id="localized-names-of-languages"></span><h3>语言的本地化名称<a class="headerlink" href="#localized-names-of-languages" title="永久链接至标题">¶</a></h3>
<dl class="function">
<dt id="django.utils.translation.get_language_info">
<code class="descname">get_language_info</code>()<a class="headerlink" href="#django.utils.translation.get_language_info" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p><code class="docutils literal notranslate"><span class="pre">get_language_info()</span></code> 函数提供关于语言的详细信息：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">activate</span><span class="p">,</span> <span class="n">get_language_info</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;fr&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">li</span> <span class="o">=</span> <span class="n">get_language_info</span><span class="p">(</span><span class="s1">&#39;de&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">li</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">],</span> <span class="n">li</span><span class="p">[</span><span class="s1">&#39;name_local&#39;</span><span class="p">],</span> <span class="n">li</span><span class="p">[</span><span class="s1">&#39;name_translated&#39;</span><span class="p">],</span> <span class="n">li</span><span class="p">[</span><span class="s1">&#39;bidi&#39;</span><span class="p">])</span>
<span class="go">German Deutsch Allemand False</span>
</pre></div>
</div>
<p>字典的 <code class="docutils literal notranslate"><span class="pre">name</span></code>, <code class="docutils literal notranslate"><span class="pre">name_local</span></code>, 以及 <code class="docutils literal notranslate"><span class="pre">name_translated</span></code> 属性分别包含用英语、该语言本身以及当前启用的语言的名称。<code class="docutils literal notranslate"><span class="pre">bidi</span></code> 属性仅对于双向(bi-directional)语言为 True 。</p>
<p>语言信息的来源是 <code class="docutils literal notranslate"><span class="pre">django.conf.locale</span></code> 模块。模板代码也可以使用类似方式访问信息。</p>
</div>
</div>
<div class="section" id="s-internationalization-in-template-code">
<span id="s-specifying-translation-strings-in-template-code"></span><span id="internationalization-in-template-code"></span><span id="specifying-translation-strings-in-template-code"></span><h2>在模板代码中国际化<a class="headerlink" href="#internationalization-in-template-code" title="永久链接至标题">¶</a></h2>
<p><a class="reference internal" href="../../ref/templates/language.html"><span class="doc">Django templates</span></a> 中的翻译使用两个模板标签，并且语法与 Python 代码中的语法略有不同。要使模板访问这些标签，需要在模板顶部加入 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">load</span> <span class="pre">i18n</span> <span class="pre">%}</span></code> 。与所有模板标签一样，这个标签需要在所有需要翻译的模板中加载，甚至那些从其他模板继承(extend)而来的模板，也需要继承  <code class="docutils literal notranslate"><span class="pre">i18n</span></code> 标签。</p>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">在渲染模板的时候，翻译后的字符串不会被转义。这使你在翻译中包含 HTML ，比如为了强调，但潜在的危险字符（比如 <code class="docutils literal notranslate"><span class="pre">&quot;</span></code>）也将保持不变。</p>
</div>
<span class="target" id="std:templatetag-trans"></span><div class="section" id="s-translate-template-tag">
<span id="s-std:templatetag-translate"></span><span id="translate-template-tag"></span><span id="std:templatetag-translate"></span><h3><code class="docutils literal notranslate"><span class="pre">translate</span></code> 模板标签<a class="headerlink" href="#translate-template-tag" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">translate</span> <span class="pre">%}</span></code> 模板标签可以翻译常量字符串（用单引号或双引号括起来）或变量内容：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;This is the title.&quot;</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="nv">myvar</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>如果存在 <code class="docutils literal notranslate"><span class="pre">noop</span></code> 选项，则变量查找仍会发生，但会跳过翻译。这在“剔除”将来需要翻译的内容时非常有用：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;myvar&quot;</span> <span class="nv">noop</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>在内部，内联翻译使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext" title="django.utils.translation.gettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext()</span></code></a> 调用。</p>
<p>如果模板变量（如上面的 <code class="docutils literal notranslate"><span class="pre">myvar</span></code> ）传递给了一个标签，该标签将在运行时首先将这些变量解析为字符串，然后在消息目录里查找变量。</p>
<p>在 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">translate</span> <span class="pre">%}</span></code> 中，不可能在字符串中混合模板变量。如果你的翻译需要变量字符串（占位符），请使用 <a class="reference internal" href="#std:templatetag-blocktranslate"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code></a> 替代。</p>
<p>如果你想检索翻译的字符串而不显示它，那你可以使用下面的语法：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;This is the title&quot;</span> <span class="k">as</span> <span class="nv">the_title</span> <span class="cp">%}</span>

<span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">the_title</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;description&quot;</span> <span class="na">content</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">the_title</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>事实上你可以使用这个办法来获取一个在模板中多处使用的字符串，或将输出作为其他模板标签或过滤器的参数：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;starting point&quot;</span> <span class="k">as</span> <span class="nv">start</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;end point&quot;</span> <span class="k">as</span> <span class="nv">end</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;La Grande Boucle&quot;</span> <span class="k">as</span> <span class="nv">race</span> <span class="cp">%}</span>

<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>
  <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;/&quot;</span> <span class="na">title</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="cp">%}</span><span class="s">Back to &#39;</span><span class="cp">{{</span> <span class="nv">race</span> <span class="cp">}}</span><span class="s">&#39; homepage</span><span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span><span class="s">&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">race</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">stage</span> <span class="k">in</span> <span class="nv">tour_stages</span> <span class="cp">%}</span>
    <span class="cp">{%</span> <span class="k">cycle</span> <span class="nv">start</span> <span class="nv">end</span> <span class="cp">%}</span>: <span class="cp">{{</span> <span class="nv">stage</span> <span class="cp">}}{%</span> <span class="k">if</span> <span class="nb">forloop</span><span class="nv">.counter</span><span class="o">|</span><span class="nf">divisibleby</span><span class="o">:</span><span class="m">2</span> <span class="cp">%}</span><span class="p">&lt;</span><span class="nt">br</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>, <span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">translate</span> <span class="pre">%}</span></code> 也支持使用 <code class="docutils literal notranslate"><span class="pre">context</span></code> 关键词的 <a class="reference internal" href="#contextual-markers"><span class="std std-ref">上下文标记</span></a>：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;May&quot;</span> <span class="nv">context</span> <span class="s2">&quot;month name&quot;</span> <span class="cp">%}</span>
</pre></div>
</div>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p><code class="docutils literal notranslate"><span class="pre">trans</span></code> 标签已改名为 <code class="docutils literal notranslate"><span class="pre">translate</span></code>。 <code class="docutils literal notranslate"><span class="pre">trans</span></code> 标签仍作为别名支持，以便向后兼容。</p>
</div>
<span class="target" id="std:templatetag-blocktrans"></span></div>
<div class="section" id="s-blocktranslate-template-tag">
<span id="s-std:templatetag-blocktranslate"></span><span id="blocktranslate-template-tag"></span><span id="std:templatetag-blocktranslate"></span><h3><code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 模板标签<a class="headerlink" href="#blocktranslate-template-tag" title="永久链接至标题">¶</a></h3>
<p>与 <a class="reference internal" href="#std:templatetag-translate"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">translate</span></code></a> 标签相反，<code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 标签允许你通过使用占位符来标记复杂的句子，包括文字和可变内容的翻译：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="cp">%}</span>This string will have <span class="cp">{{</span> <span class="nv">value</span> <span class="cp">}}</span> inside.<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>要翻译模板表达式（比如，访问对象属性或使用模板过滤器），你需要绑定表达式到本地变量，以便在翻译块中使用。例如：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="k">with</span> <span class="nv">amount</span><span class="o">=</span><span class="nv">article.price</span> <span class="cp">%}</span>
That will cost $ <span class="cp">{{</span> <span class="nv">amount</span> <span class="cp">}}</span>.
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="k">with</span> <span class="nv">myvar</span><span class="o">=</span><span class="nv">value</span><span class="o">|</span><span class="nf">filter</span> <span class="cp">%}</span>
This will have <span class="cp">{{</span> <span class="nv">myvar</span> <span class="cp">}}</span> inside.
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>你可以在一个 <code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 标签内使用多个表达式：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="k">with</span> <span class="nv">book_t</span><span class="o">=</span><span class="nv">book</span><span class="o">|</span><span class="nf">title</span> <span class="nv">author_t</span><span class="o">=</span><span class="nv">author</span><span class="o">|</span><span class="nf">title</span> <span class="cp">%}</span>
This is <span class="cp">{{</span> <span class="nv">book_t</span> <span class="cp">}}</span> by <span class="cp">{{</span> <span class="nv">author_t</span> <span class="cp">}}</span>
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">仍然支持以前的更简洁的格式：<code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">with</span> <span class="pre">book|title</span> <span class="pre">as</span> <span class="pre">book_t</span> <span class="pre">and</span> <span class="pre">author|title</span> <span class="pre">as</span> <span class="pre">author_t</span> <span class="pre">%}</span></code>。</p>
</div>
<p>其他区块标签（例如 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">for</span> <span class="pre">%}</span></code> 或 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">if</span> <span class="pre">%}</span></code>）不允许放在 <code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 标签内。</p>
<p>如果解决一个区块参数失败，<code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 将回到默认语言，暂时停用当前活动的语言与 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.deactivate_all" title="django.utils.translation.deactivate_all"><code class="xref py py-func docutils literal notranslate"><span class="pre">deactivate_all()</span></code></a> 函数。</p>
<p>该标签也提供复数形式。要使用它：</p>
<ul class="simple">
<li>指定并绑定名称为 <code class="docutils literal notranslate"><span class="pre">count</span></code> 的计数器值。该值将用于选择正确的复数形式。</li>
<li>在 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 和 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">endblocktranslate</span> <span class="pre">%}</span></code> 标签中，用 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">plural</span> <span class="pre">%}</span></code> 标签指定单数和复数形式，将它们分开。</li>
</ul>
<p>一个例子：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="nv">count</span> <span class="nv">counter</span><span class="o">=</span><span class="nv">list</span><span class="o">|</span><span class="nf">length</span> <span class="cp">%}</span>
There is only one <span class="cp">{{</span> <span class="nv">name</span> <span class="cp">}}</span> object.
<span class="cp">{%</span> <span class="k">plural</span> <span class="cp">%}</span>
There are <span class="cp">{{</span> <span class="nv">counter</span> <span class="cp">}}</span> <span class="cp">{{</span> <span class="nv">name</span> <span class="cp">}}</span> objects.
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>一个更复杂的例子：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="k">with</span> <span class="nv">amount</span><span class="o">=</span><span class="nv">article.price</span> <span class="nv">count</span> <span class="nv">years</span><span class="o">=</span><span class="nv">i.length</span> <span class="cp">%}</span>
That will cost $ <span class="cp">{{</span> <span class="nv">amount</span> <span class="cp">}}</span> per year.
<span class="cp">{%</span> <span class="k">plural</span> <span class="cp">%}</span>
That will cost $ <span class="cp">{{</span> <span class="nv">amount</span> <span class="cp">}}</span> per <span class="cp">{{</span> <span class="nv">years</span> <span class="cp">}}</span> years.
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>当你同时使用复数功能和将值绑定到本地变量上时，请记住，<code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 结构在内部被转换为 <code class="docutils literal notranslate"><span class="pre">ngettext</span></code> 调用。这意味着同样的 <a class="reference internal" href="#pluralization-var-notes"><span class="std std-ref">关于 ngettext 变量的注释</span></a> 适用。</p>
<p>反向 URL 查询不能在 <code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 内进行，应事先检索（并存储）：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">url</span> <span class="s1">&#39;path.to.view&#39;</span> <span class="nv">arg</span> <span class="nv">arg2</span> <span class="k">as</span> <span class="nv">the_url</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="cp">%}</span>
This is a URL: <span class="cp">{{</span> <span class="nv">the_url</span> <span class="cp">}}</span>
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>如果你想检索翻译的字符串而不显示它，那你可以使用下面的语法：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="nv">asvar</span> <span class="nv">the_title</span> <span class="cp">%}</span>The title is <span class="cp">{{</span> <span class="nv">title</span> <span class="cp">}}</span>.<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">the_title</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;description&quot;</span> <span class="na">content</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">the_title</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>事实上你可以使用这个办法来获取一个在模板中多处使用的字符串，或将输出作为其他模板标签或过滤器的参数。</p>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 也支持使用 <code class="docutils literal notranslate"><span class="pre">context</span></code> 关键字的 <a class="reference internal" href="#contextual-markers"><span class="std std-ref">上下文标记</span></a> ：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="k">with</span> <span class="nv">name</span><span class="o">=</span><span class="nv">user.username</span> <span class="nv">context</span> <span class="s2">&quot;greeting&quot;</span> <span class="cp">%}</span>Hi <span class="cp">{{</span> <span class="nv">name</span> <span class="cp">}}{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 支持的另一个功能是 <code class="docutils literal notranslate"><span class="pre">trimmed</span></code> 选项。这个选项将删除换行字符的开头和结尾的内容的 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 标签，取代任何空格的开头和结尾的一行，并合并所有行成一个使用空格字符分开。这对于缩进 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 标签的内容是相当有用的，而不会让缩进字符最终出现在 PO 文件的相应条目中，这使得翻译过程更容易。</p>
<p>例如，以下 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">blocktranslate</span> <span class="pre">%}</span></code> 标签：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="nv">trimmed</span> <span class="cp">%}</span>
  First sentence.
  Second paragraph.
<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>如果没有 <code class="docutils literal notranslate"><span class="pre">trimmed</span></code> 选项，那么 PO 文件中的条目 <code class="docutils literal notranslate"><span class="pre">&quot;First</span> <span class="pre">sentence.</span> <span class="pre">Second</span> <span class="pre">paragraph.&quot;</span></code> 成为 <code class="docutils literal notranslate"><span class="pre">&quot;\n</span> <span class="pre">First</span> <span class="pre">sentence.\n</span> <span class="pre">Second</span> <span class="pre">sentence.\n&quot;</span></code>。</p>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p><code class="docutils literal notranslate"><span class="pre">blocktrans</span></code> 标签已改名为 <code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code>。<code class="docutils literal notranslate"><span class="pre">blocktrans</span></code> 标签仍作为别名支持，以便向后兼容。</p>
</div>
</div>
<div class="section" id="s-string-literals-passed-to-tags-and-filters">
<span id="string-literals-passed-to-tags-and-filters"></span><h3>传递字符串给标签和过滤器<a class="headerlink" href="#string-literals-passed-to-tags-and-filters" title="永久链接至标题">¶</a></h3>
<p>可以使用常见的 <code class="docutils literal notranslate"><span class="pre">_()</span></code> 语法将翻译的字符串作为参数传递给标签和过滤器：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">some_tag</span> <span class="kp">_</span><span class="o">(</span><span class="s2">&quot;Page not found&quot;</span><span class="o">)</span> <span class="nv">value</span><span class="o">|</span><span class="nf">yesno</span><span class="o">:</span><span class="kp">_</span><span class="o">(</span><span class="s2">&quot;yes,no&quot;</span><span class="o">)</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>在这种情况下，标签和过滤器将看到翻译后的字符串，因此它们不需要知道翻译。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">在这个例子里，翻译基础结构将被传递字符串 <code class="docutils literal notranslate"><span class="pre">&quot;yes,no&quot;</span></code> ，而不是单独的字符 <code class="docutils literal notranslate"><span class="pre">&quot;yes&quot;</span></code> 和 <code class="docutils literal notranslate"><span class="pre">&quot;no&quot;</span></code> 。翻译后的字符串需要包含逗号，以便过滤器解析代码时知道如何分割参数。比如，一名德国翻译者可以将 <code class="docutils literal notranslate"><span class="pre">&quot;yes,no&quot;</span></code> 翻译为 <code class="docutils literal notranslate"><span class="pre">&quot;ja,nein&quot;</span></code> （保持逗号不变）。</p>
</div>
</div>
<div class="section" id="s-comments-for-translators-in-templates">
<span id="s-translator-comments-in-templates"></span><span id="comments-for-translators-in-templates"></span><span id="translator-comments-in-templates"></span><h3>模板内对翻译的注释<a class="headerlink" href="#comments-for-translators-in-templates" title="永久链接至标题">¶</a></h3>
<p>就像 Python 代码一样，对翻译者的提示可以使用注释来标注，使用 <a class="reference internal" href="../../ref/templates/builtins.html#std:templatetag-comment"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">comment</span></code></a> 标签：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">comment</span> <span class="cp">%}</span><span class="c">Translators: View verb</span><span class="cp">{%</span> <span class="k">endcomment</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;View&quot;</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">comment</span> <span class="cp">%}</span><span class="c">Translators: Short intro blurb</span><span class="cp">{%</span> <span class="k">endcomment</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="cp">%}</span>A multiline translatable
literal.<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>或者使用 <code class="docutils literal notranslate"><span class="pre">{#</span></code> ... <code class="docutils literal notranslate"><span class="pre">#}</span></code>&nbsp; 单行注释：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="c">{# Translators: Label of a button that triggers search #}</span>
<span class="p">&lt;</span><span class="nt">button</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;Go&quot;</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>

<span class="c">{# Translators: This is a text of the base template #}</span>
<span class="cp">{%</span> <span class="k">blocktranslate</span> <span class="cp">%}</span>Ambiguous translatable block of text<span class="cp">{%</span> <span class="k">endblocktranslate</span> <span class="cp">%}</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>为了完整起见，这些是生成 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件的相应片段：</p>
<div class="last highlight-po notranslate"><div class="highlight"><pre><span></span><span class="c1">#. Translators: View verb</span>
<span class="c1"># path/to/template/file.html:10</span>
<span class="nv">msgid</span> <span class="s">&quot;View&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>

<span class="c1">#. Translators: Short intro blurb</span>
<span class="c1"># path/to/template/file.html:13</span>
<span class="nv">msgid</span> <span class="s">&quot;&quot;</span>
<span class="s">&quot;A multiline translatable&quot;</span>
<span class="s">&quot;literal.&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>

<span class="c1"># ...</span>

<span class="c1">#. Translators: Label of a button that triggers search</span>
<span class="c1"># path/to/template/file.html:100</span>
<span class="nv">msgid</span> <span class="s">&quot;Go&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>

<span class="c1">#. Translators: This is a text of the base template</span>
<span class="c1"># path/to/template/file.html:103</span>
<span class="nv">msgid</span> <span class="s">&quot;Ambiguous translatable block of text&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-switching-language-in-templates">
<span id="s-std:templatetag-language"></span><span id="switching-language-in-templates"></span><span id="std:templatetag-language"></span><h3>在模板中选择语言<a class="headerlink" href="#switching-language-in-templates" title="永久链接至标题">¶</a></h3>
<p>如果想在模板中选择语言，可以使用 <code class="docutils literal notranslate"><span class="pre">language</span></code> 模板标签：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">load</span> <span class="nv">i18n</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">get_current_language</span> <span class="k">as</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">%}</span>
<span class="c">&lt;!-- Current language: </span><span class="cp">{{</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">}}</span><span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;Welcome to our page&quot;</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>

<span class="cp">{%</span> <span class="k">language</span> <span class="s1">&#39;en&#39;</span> <span class="cp">%}</span>
    <span class="cp">{%</span> <span class="k">get_current_language</span> <span class="k">as</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">%}</span>
    <span class="c">&lt;!-- Current language: </span><span class="cp">{{</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">}}</span><span class="c"> --&gt;</span>
    <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;Welcome to our page&quot;</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endlanguage</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>第一次出现的 &quot;Welcome to our page&quot; 使用当前语言，后面出现的使用英语。</p>
</div>
<div class="section" id="s-other-tags">
<span id="s-i18n-template-tags"></span><span id="other-tags"></span><span id="i18n-template-tags"></span><h3>其他标签<a class="headerlink" href="#other-tags" title="永久链接至标题">¶</a></h3>
<p>下面这些标签同样需要先引入 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">load</span> <span class="pre">i18n</span> <span class="pre">%}</span></code>.</p>
<div class="section" id="s-get-available-languages">
<span id="s-std:templatetag-get_available_languages"></span><span id="get-available-languages"></span><span id="std:templatetag-get_available_languages"></span><h4><code class="docutils literal notranslate"><span class="pre">get_available_languages</span></code><a class="headerlink" href="#get-available-languages" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_available_languages</span> <span class="pre">as</span> <span class="pre">LANGUAGES</span> <span class="pre">%}</span></code> 返回一个元组列表，其中第一个元素是:term:<cite>language code</cite>，第二个元素是语言名称(翻译成当前活动的语言环境)。</p>
</div>
<div class="section" id="s-get-current-language">
<span id="s-std:templatetag-get_current_language"></span><span id="get-current-language"></span><span id="std:templatetag-get_current_language"></span><h4><code class="docutils literal notranslate"><span class="pre">get_current_language</span></code><a class="headerlink" href="#get-current-language" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_current_language</span> <span class="pre">as</span> <span class="pre">LANGUAGE_CODE</span> <span class="pre">%}</span></code> 返回字符串类型的当前用户首选语言. 类似: <code class="docutils literal notranslate"><span class="pre">en-us</span></code>. 详情参阅 <a class="reference internal" href="#how-django-discovers-language-preference"><span class="std std-ref">Django 如何发现语言偏好</span></a>.</p>
</div>
<div class="section" id="s-get-current-language-bidi">
<span id="s-std:templatetag-get_current_language_bidi"></span><span id="get-current-language-bidi"></span><span id="std:templatetag-get_current_language_bidi"></span><h4><code class="docutils literal notranslate"><span class="pre">get_current_language_bidi</span></code><a class="headerlink" href="#get-current-language-bidi" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_current_language_bidi</span> <span class="pre">as</span> <span class="pre">LANGUAGE_BIDI</span> <span class="pre">%}</span></code> 返回当前语言文字的阅读方向。如果是 <code class="docutils literal notranslate"><span class="pre">True</span></code> ，则是从右向左阅读的语言，比如希伯来语，阿拉伯语。如果是 <code class="docutils literal notranslate"><span class="pre">False</span></code> ，则是从左向右阅读的语言，比如英语，法语，德语等。</p>
</div>
<div class="section" id="s-i18n-context-processor">
<span id="s-template-translation-vars"></span><span id="i18n-context-processor"></span><span id="template-translation-vars"></span><h4><code class="docutils literal notranslate"><span class="pre">i18n</span></code> 上下文处理器<a class="headerlink" href="#i18n-context-processor" title="永久链接至标题">¶</a></h4>
<p>如果启用了 <a class="reference internal" href="../../ref/templates/api.html#django.template.context_processors.i18n" title="django.template.context_processors.i18n"><code class="xref py py-class docutils literal notranslate"><span class="pre">django.template.context_processors.i18n</span></code></a> 上下文处理器，则每个 <code class="docutils literal notranslate"><span class="pre">RequestContext</span></code> 都可以访问上面所定义的 <code class="docutils literal notranslate"><span class="pre">LANGUAGES</span></code>, <code class="docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code> 和 <code class="docutils literal notranslate"><span class="pre">LANGUAGE_BIDI</span></code> 。</p>
</div>
<div class="section" id="s-get-language-info">
<span id="s-std:templatetag-get_language_info"></span><span id="get-language-info"></span><span id="std:templatetag-get_language_info"></span><h4><code class="docutils literal notranslate"><span class="pre">get_language_info</span></code><a class="headerlink" href="#get-language-info" title="永久链接至标题">¶</a></h4>
<p>你也可以查找关于任何使用支持模板标签和过滤器的可用语言的信息。为了得到单一语言的信息，可以使用 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_language_info</span> <span class="pre">%}</span></code> 标签：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">get_language_info</span> <span class="nv">for</span> <span class="nv">LANGUAGE_CODE</span> <span class="k">as</span> <span class="nv">lang</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">get_language_info</span> <span class="nv">for</span> <span class="s2">&quot;pl&quot;</span> <span class="k">as</span> <span class="nv">lang</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>然后，可以访问以下信息：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span>Language code: <span class="cp">{{</span> <span class="nv">lang.code</span> <span class="cp">}}</span><span class="p">&lt;</span><span class="nt">br</span><span class="p">&gt;</span>
Name of language: <span class="cp">{{</span> <span class="nv">lang.name_local</span> <span class="cp">}}</span><span class="p">&lt;</span><span class="nt">br</span><span class="p">&gt;</span>
Name in English: <span class="cp">{{</span> <span class="nv">lang.name</span> <span class="cp">}}</span><span class="p">&lt;</span><span class="nt">br</span><span class="p">&gt;</span>
Bi-directional: <span class="cp">{{</span> <span class="nv">lang.bidi</span> <span class="cp">}}</span>
Name in the active language: <span class="cp">{{</span> <span class="nv">lang.name_translated</span> <span class="cp">}}</span>
</pre></div>
</div>
</div>
<div class="section" id="s-get-language-info-list">
<span id="s-std:templatetag-get_language_info_list"></span><span id="get-language-info-list"></span><span id="std:templatetag-get_language_info_list"></span><h4><code class="docutils literal notranslate"><span class="pre">get_language_info_list</span></code><a class="headerlink" href="#get-language-info-list" title="永久链接至标题">¶</a></h4>
<p>你也可以使用 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_language_info_list</span> <span class="pre">%}</span></code> 模板标签来检索语言列表的信息（例如，<a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGES"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGES</span></code></a> 中指定的有效语言）。查看 <a class="reference internal" href="#set-language-redirect-view"><span class="std std-ref">关于 set_language 重定向视图的章节</span></a> 了解如何使用 <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_language_info_list</span> <span class="pre">%}</span></code> 来显示语言选择器。</p>
<p>除元组的 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGES"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGES</span></code></a> 样式列表之外，<code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">get_language_info_list</span> <span class="pre">%}</span></code> 也支持语言代码列表。如果在视图中这么做：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">context</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;available_languages&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;en&#39;</span><span class="p">,</span> <span class="s1">&#39;es&#39;</span><span class="p">,</span> <span class="s1">&#39;fr&#39;</span><span class="p">]}</span>
<span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;mytemplate.html&#39;</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>
</pre></div>
</div>
<p>你可以在模板中遍历这些语言：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">get_language_info_list</span> <span class="nv">for</span> <span class="nv">available_languages</span> <span class="k">as</span> <span class="nv">langs</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">lang</span> <span class="k">in</span> <span class="nv">langs</span> <span class="cp">%}</span> ... <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div>
</div>
<span class="target" id="std:templatefilter-language_name"></span><span class="target" id="std:templatefilter-language_name_local"></span><span class="target" id="std:templatefilter-language_bidi"></span></div>
<div class="section" id="s-template-filters">
<span id="s-std:templatefilter-language_name_translated"></span><span id="template-filters"></span><span id="std:templatefilter-language_name_translated"></span><h4>模板过滤器<a class="headerlink" href="#template-filters" title="永久链接至标题">¶</a></h4>
<p>为方便起见，还提供了一些过滤器：</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">LANGUAGE_CODE|language_name</span> <span class="pre">}}</span></code> (&quot;German&quot;)</li>
<li><code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">LANGUAGE_CODE|language_name_local</span> <span class="pre">}}</span></code> (&quot;Deutsch&quot;)</li>
<li><code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">LANGUAGE_CODE|language_bidi</span> <span class="pre">}}</span></code> (False)</li>
<li><code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">LANGUAGE_CODE|language_name_translated</span> <span class="pre">}}</span></code> (&quot;německy&quot;, 当活动语言为捷克语时)</li>
</ul>
</div>
</div>
</div>
<div class="section" id="s-internationalization-in-javascript-code">
<span id="internationalization-in-javascript-code"></span><h2>国际化：在 JavaScript&nbsp;代码里<a class="headerlink" href="#internationalization-in-javascript-code" title="永久链接至标题">¶</a></h2>
<p>向 JavaScript 添加翻译会带来一些问题：</p>
<ul class="simple">
<li>JavaScript 代码无权访问 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 实现。</li>
<li>JavaScript 代码无权访问 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 或 <code class="docutils literal notranslate"><span class="pre">.mo</span></code> 文件；它们需要通过服务器传递。</li>
<li>JavaScript 的翻译目录应该尽可能小。</li>
</ul>
<p>Django 为这三个问题提供了解决方案：它将翻译传递给Javascript，因此你可以从 JavaScript 内部调用 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 等。</p>
<p>解决这三个问题的主要解决办法是下面的 <code class="docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code> 视图，该视图生成一个JavaScript 库，该库具有模仿 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 接口的函数，外加一个翻译字符串数组。</p>
<div class="section" id="s-module-django.views.i18n">
<span id="s-the-javascriptcatalog-view"></span><span id="module-django.views.i18n"></span><span id="the-javascriptcatalog-view"></span><h3><code class="docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code> 视图<a class="headerlink" href="#module-django.views.i18n" title="永久链接至标题">¶</a></h3>
<dl class="class">
<dt id="django.views.i18n.JavaScriptCatalog">
<em class="property">class </em><code class="descname">JavaScriptCatalog</code><a class="headerlink" href="#django.views.i18n.JavaScriptCatalog" title="永久链接至目标">¶</a></dt>
<dd><p>一个视图，该视图生成一个 JavaScript 代码库，该库带有一个模仿 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 界面的函数，外加一个翻译字符串的数组。</p>
<p><strong>属性</strong></p>
<dl class="attribute">
<dt id="django.views.i18n.JavaScriptCatalog.domain">
<code class="descname">domain</code><a class="headerlink" href="#django.views.i18n.JavaScriptCatalog.domain" title="永久链接至目标">¶</a></dt>
<dd><p>翻译域包含要添加到视图输出中的字符串。默认为 <code class="docutils literal notranslate"><span class="pre">'djangojs'</span></code> 。</p>
</dd></dl>

<dl class="attribute">
<dt id="django.views.i18n.JavaScriptCatalog.packages">
<code class="descname">packages</code><a class="headerlink" href="#django.views.i18n.JavaScriptCatalog.packages" title="永久链接至目标">¶</a></dt>
<dd><p>已安装的应用程序的程序名列表。这些 app 应包含一个 <code class="docutils literal notranslate"><span class="pre">locale</span></code> 目录。所有这些目录加上  <a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a>&nbsp; 里的目录会合并到一个目录里。默认是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ，意味着在 JavaScript 输出中提供所有来自 <a class="reference internal" href="../../ref/settings.html#std:setting-INSTALLED_APPS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">INSTALLED_APPS</span></code></a> 的可用翻译。</p>
</dd></dl>

<p><strong>默认值实例</strong> ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.i18n</span> <span class="kn">import</span> <span class="n">JavaScriptCatalog</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;jsi18n/&#39;</span><span class="p">,</span> <span class="n">JavaScriptCatalog</span><span class="o">.</span><span class="n">as_view</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;javascript-catalog&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
<p><strong>自定义包实例</strong> ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;jsi18n/myapp/&#39;</span><span class="p">,</span>
         <span class="n">JavaScriptCatalog</span><span class="o">.</span><span class="n">as_view</span><span class="p">(</span><span class="n">packages</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;your.app.label&#39;</span><span class="p">]),</span>
         <span class="n">name</span><span class="o">=</span><span class="s1">&#39;javascript-catalog&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>如果你的根 URLconf 使用 <a class="reference internal" href="#django.conf.urls.i18n.i18n_patterns" title="django.conf.urls.i18n.i18n_patterns"><code class="xref py py-func docutils literal notranslate"><span class="pre">i18n_patterns()</span></code></a> ，<code class="docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code> 也必须被 <code class="docutils literal notranslate"><span class="pre">i18n_patterns()</span></code> 包装，这样目录才会被正确的生成。</p>
<p><code class="docutils literal notranslate"><span class="pre">i18n_patterns()</span></code> 实例：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.conf.urls.i18n</span> <span class="kn">import</span> <span class="n">i18n_patterns</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="n">i18n_patterns</span><span class="p">(</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;jsi18n/&#39;</span><span class="p">,</span> <span class="n">JavaScriptCatalog</span><span class="o">.</span><span class="n">as_view</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;javascript-catalog&#39;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
</div>
</dd></dl>

<p>后面出现的 <code class="docutils literal notranslate"><span class="pre">packages</span></code> 参数比前面出现的参数优先级更高。在相同文字出现冲突翻译的时候，这点很重要。</p>
<p>如果你使用多个 <code class="docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code> 视图，并且它们中的某些视图定义了相同的字符串，那么最后加载的目录中的字符串拥有优先级。</p>
</div>
<div class="section" id="s-using-the-javascript-translation-catalog">
<span id="using-the-javascript-translation-catalog"></span><h3>使用 JavaScript 翻译目录<a class="headerlink" href="#using-the-javascript-translation-catalog" title="永久链接至标题">¶</a></h3>
<p>要使用目录，请像这样引入动态生成的js：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{%</span> <span class="k">url</span> <span class="s1">&#39;javascript-catalog&#39;</span> <span class="cp">%}</span><span class="s">&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>这使用反向 URL 查询来查找 JavaScript 目录视图。当加载目录后，JavaScript 代码能使用以下方法：</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">gettext</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">ngettext</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">interpolate</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">get_format</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">gettext_noop</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">pgettext</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">npgettext</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">pluralidx</span></code></li>
</ul>
<div class="section" id="s-gettext">
<span id="gettext"></span><h4><code class="docutils literal notranslate"><span class="pre">gettext</span></code><a class="headerlink" href="#gettext" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">gettext</span></code> 函数的行为类似于 Python 代码中的标准 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 接口：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">gettext</span><span class="p">(</span><span class="s1">&#39;this is to be translated&#39;</span><span class="p">));</span>
</pre></div>
</div>
</div>
<div class="section" id="s-ngettext">
<span id="ngettext"></span><h4><code class="docutils literal notranslate"><span class="pre">ngettext</span></code><a class="headerlink" href="#ngettext" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">ngettext</span></code> 函数提供一个接口来复数化词组和短语：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span> <span class="nx">objectCount</span> <span class="o">=</span> <span class="mf">1</span> <span class="c1">// or 0, or 2, or 3, ...</span>
<span class="kd">const</span> <span class="nx">string</span> <span class="o">=</span> <span class="nx">ngettext</span><span class="p">(</span>
    <span class="s1">&#39;literal for the singular case&#39;</span><span class="p">,</span>
    <span class="s1">&#39;literal for the plural case&#39;</span><span class="p">,</span>
    <span class="nx">objectCount</span>
<span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="s-interpolate">
<span id="interpolate"></span><h4><code class="docutils literal notranslate"><span class="pre">interpolate</span></code><a class="headerlink" href="#interpolate" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">interpolate</span></code> 函数支持动态填充格式字符串(format string)。插值语法借鉴自 Python，因此 <code class="docutils literal notranslate"><span class="pre">interpolate</span></code> 函数支持位置插值和命名插值。</p>
<ul>
<li><p class="first">位置插入：<code class="docutils literal notranslate"><span class="pre">obj</span></code> 包含一个 JavaScript 数组对象，它的元素值随后以相同的顺序依次插值到相应的 <code class="docutils literal notranslate"><span class="pre">fmt</span></code> 占位符中。例如：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span> <span class="nx">formats</span> <span class="o">=</span> <span class="nx">ngettext</span><span class="p">(</span>
  <span class="s1">&#39;There is %s object. Remaining: %s&#39;</span><span class="p">,</span>
  <span class="s1">&#39;There are %s objects. Remaining: %s&#39;</span><span class="p">,</span>
  <span class="mf">11</span>
<span class="p">);</span>
<span class="kd">const</span> <span class="nx">string</span> <span class="o">=</span> <span class="nx">interpolate</span><span class="p">(</span><span class="nx">formats</span><span class="p">,</span> <span class="p">[</span><span class="mf">11</span><span class="p">,</span> <span class="mf">20</span><span class="p">]);</span>
<span class="c1">// string is &#39;There are 11 objects. Remaining: 20&#39;</span>
</pre></div>
</div>
</li>
<li><p class="first">命名插入：通过将可选的布尔 <code class="docutils literal notranslate"><span class="pre">named</span></code> 参数设为 <code class="docutils literal notranslate"><span class="pre">true</span></code> 来选择这个模式。<code class="docutils literal notranslate"><span class="pre">obj</span></code> 包含 JavaScript 对象或者关联数组。例如：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">count</span><span class="o">:</span> <span class="mf">10</span><span class="p">,</span>
  <span class="nx">total</span><span class="o">:</span> <span class="mf">50</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">formats</span> <span class="o">=</span> <span class="nx">ngettext</span><span class="p">(</span>
    <span class="s1">&#39;Total: %(total)s, there is %(count)s object&#39;</span><span class="p">,</span>
    <span class="s1">&#39;there are %(count)s of a total of %(total)s objects&#39;</span><span class="p">,</span>
    <span class="nx">data</span><span class="p">.</span><span class="nx">count</span>
<span class="p">);</span>
<span class="kd">const</span> <span class="nx">string</span> <span class="o">=</span> <span class="nx">interpolate</span><span class="p">(</span><span class="nx">formats</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</pre></div>
</div>
</li>
</ul>
<p>尽管如此，你不应该使用字符串插值：这仍然是 JavaScript，因此代码必须进行重复的正则表达式替换。这并不像 Python 中的字符串插值那么快，所以请确保你真的需要这么做（比如，与 <code class="docutils literal notranslate"><span class="pre">ngettext</span></code> 结合产生合适的复数形式）。</p>
</div>
<div class="section" id="s-get-format">
<span id="get-format"></span><h4><code class="docutils literal notranslate"><span class="pre">get_format</span></code><a class="headerlink" href="#get-format" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">get_format</span></code> 函数可以访问已配置的 i18n 格式化设置，而且可以检索指定配置名称的格式字符串：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">get_format</span><span class="p">(</span><span class="s1">&#39;DATE_FORMAT&#39;</span><span class="p">));</span>
<span class="c1">// &#39;N j, Y&#39;</span>
</pre></div>
</div>
<p>它可以访问以下设置：</p>
<ul class="simple">
<li><a class="reference internal" href="../../ref/settings.html#std:setting-DATE_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">DATE_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-DATE_INPUT_FORMATS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">DATE_INPUT_FORMATS</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-DATETIME_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">DATETIME_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-DATETIME_INPUT_FORMATS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">DATETIME_INPUT_FORMATS</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-DECIMAL_SEPARATOR"><code class="xref std std-setting docutils literal notranslate"><span class="pre">DECIMAL_SEPARATOR</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-FIRST_DAY_OF_WEEK"><code class="xref std std-setting docutils literal notranslate"><span class="pre">FIRST_DAY_OF_WEEK</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-MONTH_DAY_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">MONTH_DAY_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-NUMBER_GROUPING"><code class="xref std std-setting docutils literal notranslate"><span class="pre">NUMBER_GROUPING</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-SHORT_DATE_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">SHORT_DATE_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-SHORT_DATETIME_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">SHORT_DATETIME_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-THOUSAND_SEPARATOR"><code class="xref std std-setting docutils literal notranslate"><span class="pre">THOUSAND_SEPARATOR</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-TIME_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">TIME_FORMAT</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-TIME_INPUT_FORMATS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">TIME_INPUT_FORMATS</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-YEAR_MONTH_FORMAT"><code class="xref std std-setting docutils literal notranslate"><span class="pre">YEAR_MONTH_FORMAT</span></code></a></li>
</ul>
<p>这对于保持与Python呈现的值的格式一致性非常有用。</p>
</div>
<div class="section" id="s-gettext-noop">
<span id="gettext-noop"></span><h4><code class="docutils literal notranslate"><span class="pre">gettext_noop</span></code><a class="headerlink" href="#gettext-noop" title="永久链接至标题">¶</a></h4>
<p>这模拟了 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 函数，但不执行任何操作，返回那传递给它的所有内容：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">gettext_noop</span><span class="p">(</span><span class="s1">&#39;this will not be translated&#39;</span><span class="p">));</span>
</pre></div>
</div>
<p>这对于在将来需要翻译的代码中删除部分代码时很有用。</p>
</div>
<div class="section" id="s-pgettext">
<span id="pgettext"></span><h4><code class="docutils literal notranslate"><span class="pre">pgettext</span></code><a class="headerlink" href="#pgettext" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">pgettext</span></code> 函数的行为类似于 Python 变体(<a class="reference internal" href="../../ref/utils.html#django.utils.translation.pgettext" title="django.utils.translation.pgettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">pgettext()</span></code></a>)，它提供了一个上下文相关的单词：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">pgettext</span><span class="p">(</span><span class="s1">&#39;month name&#39;</span><span class="p">,</span> <span class="s1">&#39;May&#39;</span><span class="p">));</span>
</pre></div>
</div>
</div>
<div class="section" id="s-npgettext">
<span id="npgettext"></span><h4><code class="docutils literal notranslate"><span class="pre">npgettext</span></code><a class="headerlink" href="#npgettext" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">npgettext</span></code> 函数的行为类似于 Python 变体(<a class="reference internal" href="../../ref/utils.html#django.utils.translation.npgettext" title="django.utils.translation.npgettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">npgettext()</span></code></a>)，它提供了一个上下文相关的 <strong>复数</strong> 单词：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">npgettext</span><span class="p">(</span><span class="s1">&#39;group&#39;</span><span class="p">,</span> <span class="s1">&#39;party&#39;</span><span class="p">,</span> <span class="mf">1</span><span class="p">));</span>
<span class="c1">// party</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">npgettext</span><span class="p">(</span><span class="s1">&#39;group&#39;</span><span class="p">,</span> <span class="s1">&#39;party&#39;</span><span class="p">,</span> <span class="mf">2</span><span class="p">));</span>
<span class="c1">// parties</span>
</pre></div>
</div>
</div>
<div class="section" id="s-pluralidx">
<span id="pluralidx"></span><h4><code class="docutils literal notranslate"><span class="pre">pluralidx</span></code><a class="headerlink" href="#pluralidx" title="永久链接至标题">¶</a></h4>
<p><code class="docutils literal notranslate"><span class="pre">pluralidx</span></code> 函数的工作方式类似于 <a class="reference internal" href="../../ref/templates/builtins.html#std:templatefilter-pluralize"><code class="xref std std-tfilter docutils literal notranslate"><span class="pre">pluralize</span></code></a> 模板过滤器，决定给定的 <code class="docutils literal notranslate"><span class="pre">count</span></code> 是否应该使用单词的复数形式：</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">pluralidx</span><span class="p">(</span><span class="mf">0</span><span class="p">));</span>
<span class="c1">// true</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">pluralidx</span><span class="p">(</span><span class="mf">1</span><span class="p">));</span>
<span class="c1">// false</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">pluralidx</span><span class="p">(</span><span class="mf">2</span><span class="p">));</span>
<span class="c1">// true</span>
</pre></div>
</div>
<p>在这种最简单的情况下，如果不需要自定义复数，那么会对整数 <code class="docutils literal notranslate"><span class="pre">1</span></code> 返回 <code class="docutils literal notranslate"><span class="pre">false</span></code> ，其他数返回 <code class="docutils literal notranslate"><span class="pre">true</span></code> 。</p>
<p>然而，在所有语言中复数化并不是这么简单。如果语言不支持复数化，那么就需要提供一个空值。</p>
<p>此外，如果复数的规则复杂，目录视图将渲染一个条件表达式。它将返回  <code class="docutils literal notranslate"><span class="pre">true</span></code> (如果是复数) 或 <code class="docutils literal notranslate"><span class="pre">false</span></code> (如果不是复数) 的值。</p>
</div>
</div>
<div class="section" id="s-the-jsoncatalog-view">
<span id="the-jsoncatalog-view"></span><h3><code class="docutils literal notranslate"><span class="pre">JSONCatalog</span></code> 视图<a class="headerlink" href="#the-jsoncatalog-view" title="永久链接至标题">¶</a></h3>
<dl class="class">
<dt id="django.views.i18n.JSONCatalog">
<em class="property">class </em><code class="descname">JSONCatalog</code><a class="headerlink" href="#django.views.i18n.JSONCatalog" title="永久链接至目标">¶</a></dt>
<dd><p>为了使用其他客户端的库来控制翻译，你可能需要利用 <code class="docutils literal notranslate"><span class="pre">JSONCatalog</span></code> 视图。它类似于 <a class="reference internal" href="#django.views.i18n.JavaScriptCatalog" title="django.views.i18n.JavaScriptCatalog"><code class="xref py py-class docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code></a> ，但返回一个 JSON 响应。</p>
<p>查看 <a class="reference internal" href="#django.views.i18n.JavaScriptCatalog" title="django.views.i18n.JavaScriptCatalog"><code class="xref py py-class docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code></a> 文档来了解关于 <code class="docutils literal notranslate"><span class="pre">domain</span></code> 和 <code class="docutils literal notranslate"><span class="pre">packages</span></code> 属性的可能值和使用。</p>
<p>响应格式如下：</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>{
    &quot;catalog&quot;: {
        # Translations catalog
    },
    &quot;formats&quot;: {
        # Language formats for date, time, etc.
    },
    &quot;plural&quot;: &quot;...&quot;  # Expression for plural forms, or null.
}
</pre></div>
</div>
</dd></dl>

</div>
<div class="section" id="s-note-on-performance">
<span id="note-on-performance"></span><h3>性能说明<a class="headerlink" href="#note-on-performance" title="永久链接至标题">¶</a></h3>
<p>各种 JavaScript/JSON i18n 视图在每次请求时从 <code class="docutils literal notranslate"><span class="pre">.mo</span></code> 文件生成日历。因为其输出是恒定的，至少对于给定版本的站点来说，它是缓存的一个很好的选择。</p>
<p>服务端缓存将减少 CPU 负载。使用 <a class="reference internal" href="../cache.html#django.views.decorators.cache.cache_page" title="django.views.decorators.cache.cache_page"><code class="xref py py-func docutils literal notranslate"><span class="pre">cache_page()</span></code></a> 装饰器很容易实现。要在翻译变化时让缓存失效，需要提供一个版本相关的键前缀，如下例所示，或将视图映射到版本相关的 URL ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.views.decorators.cache</span> <span class="kn">import</span> <span class="n">cache_page</span>
<span class="kn">from</span> <span class="nn">django.views.i18n</span> <span class="kn">import</span> <span class="n">JavaScriptCatalog</span>

<span class="c1"># The value returned by get_version() must change when translations change.</span>
<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;jsi18n/&#39;</span><span class="p">,</span>
         <span class="n">cache_page</span><span class="p">(</span><span class="mi">86400</span><span class="p">,</span> <span class="n">key_prefix</span><span class="o">=</span><span class="s1">&#39;js18n-</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">get_version</span><span class="p">())(</span><span class="n">JavaScriptCatalog</span><span class="o">.</span><span class="n">as_view</span><span class="p">()),</span>
         <span class="n">name</span><span class="o">=</span><span class="s1">&#39;javascript-catalog&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>客户端缓存将节省带宽并让网站加载速度变快。如果你正在使用 ETags（<a class="reference internal" href="../../ref/middleware.html#django.middleware.http.ConditionalGetMiddleware" title="django.middleware.http.ConditionalGetMiddleware"><code class="xref py py-class docutils literal notranslate"><span class="pre">ConditionalGetMiddleware</span></code></a>），那么你已经被覆盖了。否则，你可以应用条件装饰器（<a class="reference internal" href="../conditional-view-processing.html#conditional-decorators"><span class="std std-ref">conditional decorators</span></a>）。在下面的例子中，当你重启应用程序服务时，缓存将失效。</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">timezone</span>
<span class="kn">from</span> <span class="nn">django.views.decorators.http</span> <span class="kn">import</span> <span class="n">last_modified</span>
<span class="kn">from</span> <span class="nn">django.views.i18n</span> <span class="kn">import</span> <span class="n">JavaScriptCatalog</span>

<span class="n">last_modified_date</span> <span class="o">=</span> <span class="n">timezone</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;jsi18n/&#39;</span><span class="p">,</span>
         <span class="n">last_modified</span><span class="p">(</span><span class="k">lambda</span> <span class="n">req</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">:</span> <span class="n">last_modified_date</span><span class="p">)(</span><span class="n">JavaScriptCatalog</span><span class="o">.</span><span class="n">as_view</span><span class="p">()),</span>
         <span class="n">name</span><span class="o">=</span><span class="s1">&#39;javascript-catalog&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>你甚至可以在部署过程中预先生成JavaScript目录，并将其作为静态文件。该技术已在 <a class="reference external" href="https://django-statici18n.readthedocs.io/">django-statici18n</a> 中实现。</p>
</div>
</div>
<div class="section" id="s-module-django.conf.urls.i18n">
<span id="s-internationalization-in-url-patterns"></span><span id="s-url-internationalization"></span><span id="module-django.conf.urls.i18n"></span><span id="internationalization-in-url-patterns"></span><span id="url-internationalization"></span><h2>国际化：在 URL 模式中<a class="headerlink" href="#module-django.conf.urls.i18n" title="永久链接至标题">¶</a></h2>
<p>Django 提供两种方式来国际化 URL 模式：</p>
<ul class="simple">
<li>将语言前缀添加到 URL 模式的根，来使得 <a class="reference internal" href="../../ref/middleware.html#django.middleware.locale.LocaleMiddleware" title="django.middleware.locale.LocaleMiddleware"><code class="xref py py-class docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code></a> 从请求的 URL 中检测要激活的语言。</li>
<li>通过 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_lazy" title="django.utils.translation.gettext_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.gettext_lazy()</span></code></a> 函数使得 URL 模式本身可翻译。</li>
</ul>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">使用这些特性需要为每个请求设置一个激活的语言；换句话说，你需要在 <a class="reference internal" href="../../ref/settings.html#std:setting-MIDDLEWARE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">MIDDLEWARE</span></code></a> 设置中包含 <a class="reference internal" href="../../ref/middleware.html#django.middleware.locale.LocaleMiddleware" title="django.middleware.locale.LocaleMiddleware"><code class="xref py py-class docutils literal notranslate"><span class="pre">django.middleware.locale.LocaleMiddleware</span></code></a> 。</p>
</div>
<div class="section" id="s-language-prefix-in-url-patterns">
<span id="language-prefix-in-url-patterns"></span><h3>URL 模式中的语言前缀<a class="headerlink" href="#language-prefix-in-url-patterns" title="永久链接至标题">¶</a></h3>
<dl class="function">
<dt id="django.conf.urls.i18n.i18n_patterns">
<code class="descname">i18n_patterns</code>(<em>*urls</em>, <em>prefix_default_language=True</em>)<a class="headerlink" href="#django.conf.urls.i18n.i18n_patterns" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>这个函数可以在根URLconf中使用，Django 会自动将当前激活的语言代码添加到 <a class="reference internal" href="#django.conf.urls.i18n.i18n_patterns" title="django.conf.urls.i18n.i18n_patterns"><code class="xref py py-func docutils literal notranslate"><span class="pre">i18n_patterns()</span></code></a> 中定义的所有 URL 模式中。</p>
<p>设置 <code class="docutils literal notranslate"><span class="pre">prefix_default_language</span></code> 为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 会从默认语言( <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a> )中删除前缀。这在向现有网站添加翻译时非常有用，这样当前的网址就不会改变。</p>
<p>URL 模式举例：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.conf.urls.i18n</span> <span class="kn">import</span> <span class="n">i18n_patterns</span>
<span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">include</span><span class="p">,</span> <span class="n">path</span>

<span class="kn">from</span> <span class="nn">about</span> <span class="kn">import</span> <span class="n">views</span> <span class="k">as</span> <span class="n">about_views</span>
<span class="kn">from</span> <span class="nn">news</span> <span class="kn">import</span> <span class="n">views</span> <span class="k">as</span> <span class="n">news_views</span>
<span class="kn">from</span> <span class="nn">sitemap.views</span> <span class="kn">import</span> <span class="n">sitemap</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;sitemap.xml&#39;</span><span class="p">,</span> <span class="n">sitemap</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;sitemap-xml&#39;</span><span class="p">),</span>
<span class="p">]</span>

<span class="n">news_patterns</span> <span class="o">=</span> <span class="p">([</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">news_views</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;index&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;category/&lt;slug:slug&gt;/&#39;</span><span class="p">,</span> <span class="n">news_views</span><span class="o">.</span><span class="n">category</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;category&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;&lt;slug:slug&gt;/&#39;</span><span class="p">,</span> <span class="n">news_views</span><span class="o">.</span><span class="n">details</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;detail&#39;</span><span class="p">),</span>
<span class="p">],</span> <span class="s1">&#39;news&#39;</span><span class="p">)</span>

<span class="n">urlpatterns</span> <span class="o">+=</span> <span class="n">i18n_patterns</span><span class="p">(</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;about/&#39;</span><span class="p">,</span> <span class="n">about_views</span><span class="o">.</span><span class="n">main</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;about&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;news/&#39;</span><span class="p">,</span> <span class="n">include</span><span class="p">(</span><span class="n">news_patterns</span><span class="p">,</span> <span class="n">namespace</span><span class="o">=</span><span class="s1">&#39;news&#39;</span><span class="p">)),</span>
<span class="p">)</span>
</pre></div>
</div>
<p>定义这些 URL 模式后，Django 会自动将语言前缀添加到由 <code class="docutils literal notranslate"><span class="pre">i18n_patterns</span></code>  函数添加的URL模式中。例如：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">reverse</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">activate</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;en&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;sitemap-xml&#39;</span><span class="p">)</span>
<span class="go">&#39;/sitemap.xml&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:index&#39;</span><span class="p">)</span>
<span class="go">&#39;/en/news/&#39;</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;nl&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:detail&#39;</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;slug&#39;</span><span class="p">:</span> <span class="s1">&#39;news-slug&#39;</span><span class="p">})</span>
<span class="go">&#39;/nl/news/news-slug/&#39;</span>
</pre></div>
</div>
<p>如果 <code class="docutils literal notranslate"><span class="pre">prefix_default_language=False</span></code> 并且 <code class="docutils literal notranslate"><span class="pre">LANGUAGE_CODE='en'</span></code> ，URLs 将会是：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;en&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:index&#39;</span><span class="p">)</span>
<span class="go">&#39;/news/&#39;</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;nl&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:index&#39;</span><span class="p">)</span>
<span class="go">&#39;/nl/news/&#39;</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">只允许 <a class="reference internal" href="#django.conf.urls.i18n.i18n_patterns" title="django.conf.urls.i18n.i18n_patterns"><code class="xref py py-func docutils literal notranslate"><span class="pre">i18n_patterns()</span></code></a> 在根URLconf中运行。在包含的URLconf中使用它时会弹出 <a class="reference internal" href="../../ref/exceptions.html#django.core.exceptions.ImproperlyConfigured" title="django.core.exceptions.ImproperlyConfigured"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ImproperlyConfigured</span></code></a> 异常。</p>
</div>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">确保没有可能与自动添加的语言前缀冲突的非前缀 URL 模式。</p>
</div>
</div>
<div class="section" id="s-translating-url-patterns">
<span id="s-translating-urlpatterns"></span><span id="translating-url-patterns"></span><span id="translating-urlpatterns"></span><h3>翻译URL模式<a class="headerlink" href="#translating-url-patterns" title="永久链接至标题">¶</a></h3>
<p>URL模式也可以使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_lazy" title="django.utils.translation.gettext_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext_lazy()</span></code></a> 函数标记。例如：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.conf.urls.i18n</span> <span class="kn">import</span> <span class="n">i18n_patterns</span>
<span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">include</span><span class="p">,</span> <span class="n">path</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="kn">from</span> <span class="nn">about</span> <span class="kn">import</span> <span class="n">views</span> <span class="k">as</span> <span class="n">about_views</span>
<span class="kn">from</span> <span class="nn">news</span> <span class="kn">import</span> <span class="n">views</span> <span class="k">as</span> <span class="n">news_views</span>
<span class="kn">from</span> <span class="nn">sitemaps.views</span> <span class="kn">import</span> <span class="n">sitemap</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;sitemap.xml&#39;</span><span class="p">,</span> <span class="n">sitemap</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;sitemap-xml&#39;</span><span class="p">),</span>
<span class="p">]</span>

<span class="n">news_patterns</span> <span class="o">=</span> <span class="p">([</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">news_views</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;index&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;category/&lt;slug:slug&gt;/&#39;</span><span class="p">),</span> <span class="n">news_views</span><span class="o">.</span><span class="n">category</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;category&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="s1">&#39;&lt;slug:slug&gt;/&#39;</span><span class="p">,</span> <span class="n">news_views</span><span class="o">.</span><span class="n">details</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;detail&#39;</span><span class="p">),</span>
<span class="p">],</span> <span class="s1">&#39;news&#39;</span><span class="p">)</span>

<span class="n">urlpatterns</span> <span class="o">+=</span> <span class="n">i18n_patterns</span><span class="p">(</span>
    <span class="n">path</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;about/&#39;</span><span class="p">),</span> <span class="n">about_views</span><span class="o">.</span><span class="n">main</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;about&#39;</span><span class="p">),</span>
    <span class="n">path</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;news/&#39;</span><span class="p">),</span> <span class="n">include</span><span class="p">(</span><span class="n">news_patterns</span><span class="p">,</span> <span class="n">namespace</span><span class="o">=</span><span class="s1">&#39;news&#39;</span><span class="p">)),</span>
<span class="p">)</span>
</pre></div>
</div>
<p>然后你可以创建翻译，<a class="reference internal" href="../../ref/urlresolvers.html#django.urls.reverse" title="django.urls.reverse"><code class="xref py py-func docutils literal notranslate"><span class="pre">reverse()</span></code></a> 函数将以激活的语言返回URL。例如：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">reverse</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">activate</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;en&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:category&#39;</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;slug&#39;</span><span class="p">:</span> <span class="s1">&#39;recent&#39;</span><span class="p">})</span>
<span class="go">&#39;/en/news/category/recent/&#39;</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">activate</span><span class="p">(</span><span class="s1">&#39;nl&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;news:category&#39;</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;slug&#39;</span><span class="p">:</span> <span class="s1">&#39;recent&#39;</span><span class="p">})</span>
<span class="go">&#39;/nl/nieuws/categorie/recent/&#39;</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">在大多数情况下，最好只在带有语言代码前缀的模式块中使用翻译后的网址(使用  <a class="reference internal" href="#django.conf.urls.i18n.i18n_patterns" title="django.conf.urls.i18n.i18n_patterns"><code class="xref py py-func docutils literal notranslate"><span class="pre">i18n_patterns()</span></code></a> )，以避免无意中翻译的网址导致与未翻译的网址模式冲突的可能性。</p>
</div>
</div>
<div class="section" id="s-reversing-in-templates">
<span id="s-id2"></span><span id="reversing-in-templates"></span><span id="id2"></span><h3>在模板中反向解析URL<a class="headerlink" href="#reversing-in-templates" title="永久链接至标题">¶</a></h3>
<p>如果本地化的URLs在模板中解析，那么它们会始终使用当前的语言。要链接其他语言中的URL，需使用 <a class="reference internal" href="#std:templatetag-language"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">language</span></code></a> 模板标签。它可以在随附的模板部分中启用给定的语言：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">load</span> <span class="nv">i18n</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">get_available_languages</span> <span class="k">as</span> <span class="nv">languages</span> <span class="cp">%}</span>

<span class="cp">{%</span> <span class="k">translate</span> <span class="s2">&quot;View this category in:&quot;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">lang_code</span><span class="o">,</span> <span class="nv">lang_name</span> <span class="k">in</span> <span class="nv">languages</span> <span class="cp">%}</span>
    <span class="cp">{%</span> <span class="k">language</span> <span class="nv">lang_code</span> <span class="cp">%}</span>
    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{%</span> <span class="k">url</span> <span class="s1">&#39;category&#39;</span> <span class="nv">slug</span><span class="o">=</span><span class="nv">category.slug</span> <span class="cp">%}</span><span class="s">&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">lang_name</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
    <span class="cp">{%</span> <span class="k">endlanguage</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div>
</div>
<p><a class="reference internal" href="#std:templatetag-language"><code class="xref std std-ttag docutils literal notranslate"><span class="pre">language</span></code></a> 标签将语言代码作为唯一的参数。</p>
</div>
</div>
<div class="section" id="s-localization-how-to-create-language-files">
<span id="s-how-to-create-language-files"></span><span id="localization-how-to-create-language-files"></span><span id="how-to-create-language-files"></span><h2>本地化：如何创建语言文件<a class="headerlink" href="#localization-how-to-create-language-files" title="永久链接至标题">¶</a></h2>
<p>一旦标记了应用程序的字符串文字以供以后翻译，就需要写入（或获取）翻译。这里介绍一下方法。</p>
<div class="section" id="s-message-files">
<span id="message-files"></span><h3>消息文件<a class="headerlink" href="#message-files" title="永久链接至标题">¶</a></h3>
<p>首先需要为新语言创建 <a class="reference internal" href="index.html#term-message-file"><span class="xref std std-term">message file</span></a> 文件。消息文件是一个纯文本文件，代表一种语言，它包含所有可用的翻译字段以及如何以给定语言表示。消息文件扩展名是 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件。</p>
<p>Django 附带的工具 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> 会自动创建并保存这些文件。</p>
<div class="admonition-gettext-utilities admonition">
<p class="first admonition-title">Gettext 实用程序</p>
<p><code class="docutils literal notranslate"><span class="pre">makemessages</span></code> 命令（和稍后讨论的 <code class="docutils literal notranslate"><span class="pre">compilemessages</span></code> ）使用来自 GNU 文字工具集的命令行：<code class="docutils literal notranslate"><span class="pre">xgettext</span></code>, <code class="docutils literal notranslate"><span class="pre">msgfmt</span></code>, <code class="docutils literal notranslate"><span class="pre">msgmerge</span></code> 和 <code class="docutils literal notranslate"><span class="pre">msguniq</span></code> 。</p>
<p class="last"><code class="docutils literal notranslate"><span class="pre">gettext</span></code> 实用工具集支持的最低版本是 0.15 。</p>
</div>
<p>要创建或更新消息文件，需执行这个命令：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">makemessages</span> <span class="o">-</span><span class="n">l</span> <span class="n">de</span>
</pre></div>
</div>
<p>...其中 <code class="docutils literal notranslate"><span class="pre">de</span></code> 是你要创建的消息文件的 <a class="reference internal" href="index.html#term-locale-name"><span class="xref std std-term">locale name</span></a> 。例如，<code class="docutils literal notranslate"><span class="pre">pt_BR</span></code> 是葡萄牙语，<code class="docutils literal notranslate"><span class="pre">de_AT</span></code> 是奥地利德语，<code class="docutils literal notranslate"><span class="pre">id</span></code> 是印尼语。</p>
<p>脚本应该从以下两个位置之一来运行：</p>
<ul class="simple">
<li>你的 Django 项目的根目录（就是包含 <code class="docutils literal notranslate"><span class="pre">manage.py</span></code> 的那个目录）。</li>
<li>Django app的根目录。</li>
</ul>
<p>脚本会遍历你的项目源代码树或者应用程序源代码库，并抽出所有要被翻译的字符串（查看 <a class="reference internal" href="#how-django-discovers-translations"><span class="std std-ref">Django 如何发现翻译</span></a> 并确保 <a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a> 被正确设置）。它在 <code class="docutils literal notranslate"><span class="pre">locale/LANG/LC_MESSAGES</span></code> 目录中创建（或更新）消息文件。以德语为例，这个文件会是 <code class="docutils literal notranslate"><span class="pre">locale/de/LC_MESSAGES/django.po</span></code> 。</p>
<p>在项目的根目录执行 <code class="docutils literal notranslate"><span class="pre">makemessages</span></code> 命令时，提取的字符串将自动分发到合适的消息文件。这就是说，从包含 <code class="docutils literal notranslate"><span class="pre">locale</span></code> 目录的 app 文件中提取的字符串将进入该目录下的消息文件中。从不包含任何  <code class="docutils literal notranslate"><span class="pre">locale</span></code> 目录的 app 文件中提取的字符串将进入 <a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a> 中列出的第一个目录下的消息文件，如果 <a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a> 为空，则会报错。</p>
<p>默认情况下，  <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> 会检查每一个以  <code class="docutils literal notranslate"><span class="pre">.html</span></code>, <code class="docutils literal notranslate"><span class="pre">.txt</span></code> or <code class="docutils literal notranslate"><span class="pre">.py</span></code> 为后缀的文件。如果想覆盖默认值，需使用 <a class="reference internal" href="../../ref/django-admin.html#cmdoption-makemessages-extension"><code class="xref std std-option docutils literal notranslate"><span class="pre">--extension</span></code></a> 或 <code class="docutils literal notranslate"><span class="pre">-e</span></code> 选项来指定要检查的文件扩展名：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">makemessages</span> <span class="o">-</span><span class="n">l</span> <span class="n">de</span> <span class="o">-</span><span class="n">e</span> <span class="n">txt</span>
</pre></div>
</div>
<p>使用逗号和(或)多次使用 <code class="docutils literal notranslate"><span class="pre">-e</span></code> 或 <code class="docutils literal notranslate"><span class="pre">--extension</span></code> 来分隔多个扩展名：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">makemessages</span> <span class="o">-</span><span class="n">l</span> <span class="n">de</span> <span class="o">-</span><span class="n">e</span> <span class="n">html</span><span class="p">,</span><span class="n">txt</span> <span class="o">-</span><span class="n">e</span> <span class="n">xml</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">从 JavaScript 源码中创建消息文件时（<a class="reference internal" href="#creating-message-files-from-js-code"><span class="std std-ref">creating message files from JavaScript source code</span></a>），你需要使用特别的 <code class="docutils literal notranslate"><span class="pre">djangojs</span></code> 域，而不是 <code class="docutils literal notranslate"><span class="pre">-e</span> <span class="pre">js</span></code> 。</p>
</div>
<div class="admonition-using-jinja2-templates admonition">
<p class="first admonition-title">使用 Jinja2 模板？</p>
<p><a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 不识别Jinja2模板的语法。要从包含Jinja2模板的项目中提取字符串，需要使用 <a class="reference external" href="https://babel.pocoo.org/en/latest/">Babel</a> 的 <a class="reference external" href="https://babel.pocoo.org/en/latest/messages.html#message-extraction">Message Extracting</a> 。</p>
<p><code class="docutils literal notranslate"><span class="pre">babel.cfg</span></code> 配置文件示例：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Extraction from Python source files</span>
<span class="p">[</span><span class="n">python</span><span class="p">:</span> <span class="o">**.</span><span class="n">py</span><span class="p">]</span>

<span class="c1"># Extraction from Jinja2 templates</span>
<span class="p">[</span><span class="n">jinja2</span><span class="p">:</span> <span class="o">**.</span><span class="n">jinja</span><span class="p">]</span>
<span class="n">extensions</span> <span class="o">=</span> <span class="n">jinja2</span><span class="o">.</span><span class="n">ext</span><span class="o">.</span><span class="n">with_</span>
</pre></div>
</div>
<p>确保列出所有正在使用的扩展名。否则Babel不会识别这些扩展名定义的标签，并会完全忽略包含它们的Jinja2模板。</p>
<p class="last">Babel提供了与 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 类似的功能，通常可以替换它，并且不会依赖 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 。获取更多信息，请查阅关于使用消息目录（ <a class="reference external" href="https://babel.pocoo.org/en/latest/messages.html">working with message catalogs</a> ）的文档。</p>
</div>
<div class="admonition-no-gettext admonition">
<p class="first admonition-title">没有 gettext？</p>
<p class="last">如果你还没有安装 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> ，<a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 将创建一个空文件。如果是这种情况，要么安装 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> ，要么复制英文消息文件(如果可用) (<code class="docutils literal notranslate"><span class="pre">locale/en/LC_MESSAGES/django.po</span></code>) 并将其作为起点，即一个空的翻译文件。</p>
</div>
<div class="admonition-working-on-windows admonition">
<p class="first admonition-title">在 Windows 上工作？</p>
<p class="last">如果你正在使用Windows并且需要安装 GNU gettext 程序以便 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 工作，请参阅 <a class="reference internal" href="#gettext-on-windows"><span class="std std-ref">Windows 上的 gettext</span></a> 了解更多信息。</p>
</div>
<p>每个 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件包含少量的元数据（例如翻译维护者的联系方式等等）以及大量的翻译文件 —— 要翻译的字符串以及实际翻译的字段之间的映射。</p>
<p>例如，如果 Djanog 程序包含一段 <code class="docutils literal notranslate"><span class="pre">&quot;Welcome</span> <span class="pre">to</span> <span class="pre">my</span> <span class="pre">site.&quot;</span></code> 的翻译字符串，像这样：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">_</span><span class="p">(</span><span class="s2">&quot;Welcome to my site.&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>... 然后 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> 将创建一个包含以下代码片段的 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件 —— 一条消息：</p>
<div class="highlight-po notranslate"><div class="highlight"><pre><span></span><span class="kd">#: path/to/python/module.py:23</span>
<span class="nv">msgid</span> <span class="s">&quot;Welcome to my site.&quot;</span>
<span class="nv">msgstr</span> <span class="s">&quot;&quot;</span>
</pre></div>
</div>
<p>快速解释：</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">msgid</span></code> 是显示在源代码中需要翻译的字符串。不要改动它。</li>
<li><code class="docutils literal notranslate"><span class="pre">msgstr</span></code> 是你翻译后的字符串。一开始它是空的，因此你需要填充它。确保在翻译中保留引号。</li>
<li>为了方便，每个消息包含以前缀为 <code class="docutils literal notranslate"><span class="pre">#</span></code> 且位于 <code class="docutils literal notranslate"><span class="pre">msgid</span></code> 行上方的注释行的形式的注释行，这个注释行报货文件名和需要翻译字符串的行号。</li>
</ul>
<p>长消息是特殊的情况。这里，在 <code class="docutils literal notranslate"><span class="pre">msgstr</span></code> (or <code class="docutils literal notranslate"><span class="pre">msgid</span></code>) 后的第一个字符串是空字符串。然后内容本身就会在接下来的几行中以每行一串的形式写出来。这些字符串被直接连接起来。不要忘了字符串中尾部的空格，否则，它们会被粘贴在一起而不留空白！</p>
<div class="admonition-mind-your-charset admonition">
<p class="first admonition-title">注意你的字符集</p>
<p class="last">由于 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 工具的内部工作方式，以及我们在 Django 内核以及你的项目中允许 non-ASCII 源字符串，你 <strong>必须</strong> 使用 UTF-8作为你的PO文件的编码。这意味着每个人将使用相同的编码，这在 Django 处理PO文件时很重要。</p>
</div>
<div class="admonition-fuzzy-entries admonition">
<p class="first admonition-title">模糊条目</p>
<p class="last">当翻译是从例如已翻译的字符串中推断出来的时候，:djadmin:<a href="#id1"><span class="problematic" id="id2">`</span></a>makemessages`有时会生成标记为“模糊”的翻译条目。在默认情况下，模糊条目**不会**被 :djadmin:<a href="#id3"><span class="problematic" id="id4">`</span></a>compilemessages`处理。</p>
</div>
<p>要重新检查新翻译字符串的源代码和模板并更新所有语言的所有消息，运行这行：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">makemessages</span> <span class="o">-</span><span class="n">a</span>
</pre></div>
</div>
</div>
<div class="section" id="s-compiling-message-files">
<span id="compiling-message-files"></span><h3>编译消息文件<a class="headerlink" href="#compiling-message-files" title="永久链接至标题">¶</a></h3>
<p>创建消息文件后，以及每次修改它时，你需要把它编译成更有效的形式，以供 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 使用。使用 <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span></code></a> 工具来执行此操作。</p>
<p>该工具运行所有可用的 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件并创建 <code class="docutils literal notranslate"><span class="pre">.mo</span></code> 文件，这些文件是为 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 使用而优化的二进制文件。</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">compilemessages</span>
</pre></div>
</div>
<p>这就行了。可以使用你的翻译文件了。</p>
<div class="admonition-working-on-windows admonition">
<p class="first admonition-title">在 Windows 上工作？</p>
<p class="last">如果你正在使用Windows并且需要安装 GNU gettext 程序以便 <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span></code></a> 工作，请参阅 <a class="reference internal" href="#gettext-on-windows"><span class="std std-ref">Windows 上的 gettext</span></a> 了解更多信息。</p>
</div>
<div class="admonition-po-files-encoding-and-bom-usage admonition">
<p class="first admonition-title">.po files: Encoding 和 BOM 用法.</p>
<p class="last">Django 只支持使用UTF-8编码的 <code class="docutils literal notranslate"><span class="pre">.po</span></code> 文件并且没有任何BOM(字节顺序标记),因此如果文本编辑器默认在文件开头添加这个标记,那么你需要重新配置它.</p>
</div>
</div>
<div class="section" id="s-troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs">
<span id="troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs"></span><h3>疑难解答: <code class="docutils literal notranslate"><span class="pre">gettext()</span></code> 在带有百分号的字符串中错误地检测 <code class="docutils literal notranslate"><span class="pre">python-format</span></code><a class="headerlink" href="#troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs" title="永久链接至标题">¶</a></h3>
<p>在某些情况下,带有百分号的字符串跟着一个空格和一个字符串转换换类型( <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#old-string-formatting" title="(在 Python v3.10)"><span class="xref std std-ref">string conversion type</span></a> ) (例如 <code class="docutils literal notranslate"><span class="pre">_(&quot;10%</span> <span class="pre">interest&quot;)</span></code> ),:func:<cite>~django.utils.translation.gettext</cite> 会错误地使用 <code class="docutils literal notranslate"><span class="pre">python-format</span></code> 标记字符串.</p>
<p>如果试着使用已被错误标记的字符串来编译消息文件,会得到一个消息,例如&quot; 'msgid' 和 'msgstr' 格式数量不匹配&quot;( number of format specifications in 'msgid' and 'msgstr' does not match ),或者&quot;'msgstr' 不是有效的 Python 格式字符串,与'msgid'不同 &quot;( 'msgstr' is not a valid Python format string, unlike 'msgid').</p>
<p>要解决这个问题，可以通过添加第二个百分号来转义百分号：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext</span> <span class="k">as</span> <span class="n">_</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">&quot;10</span><span class="si">%%</span><span class="s2"> interest&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>或者可以使用非python格式（ <code class="docutils literal notranslate"><span class="pre">no-python-format</span></code> ），这样所有百分号会被视为文字：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># xgettext:no-python-format</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">&quot;10</span><span class="si">% i</span><span class="s2">nterest&quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-creating-message-files-from-javascript-source-code">
<span id="s-creating-message-files-from-js-code"></span><span id="creating-message-files-from-javascript-source-code"></span><span id="creating-message-files-from-js-code"></span><h3>从 JavaScript 源码中创建消息文件<a class="headerlink" href="#creating-message-files-from-javascript-source-code" title="永久链接至标题">¶</a></h3>
<p>使用 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> ，你可以像其他Django消息文件一样创建并更新消息文件。唯一的区别是，你需要提供一个 <code class="docutils literal notranslate"><span class="pre">-d</span> <span class="pre">djangojs</span></code> 参数，明确指定gettext术语中的域，本例中是 <code class="docutils literal notranslate"><span class="pre">djangojs</span></code>  域，如下所示：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">django</span><span class="o">-</span><span class="n">admin</span> <span class="n">makemessages</span> <span class="o">-</span><span class="n">d</span> <span class="n">djangojs</span> <span class="o">-</span><span class="n">l</span> <span class="n">de</span>
</pre></div>
</div>
<p>这会创建或更新德语的JavaScript 消息文件。更新消息文件后，像执行普通 Django 消息文件那样运行  <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span></code></a> 即可。</p>
</div>
<div class="section" id="s-gettext-on-windows">
<span id="s-id3"></span><span id="gettext-on-windows"></span><span id="id3"></span><h3>Windows 上的 <code class="docutils literal notranslate"><span class="pre">gettext</span></code><a class="headerlink" href="#gettext-on-windows" title="永久链接至标题">¶</a></h3>
<p>仅适用于需要提取消息ID或编译消息文件（<code class="docutils literal notranslate"><span class="pre">.po</span></code>）的场景。翻译工作本身涉及编辑这种已存在的文件，但如果你想创建你自己的消息文件，或者想要测试或编译一个已改动的消息文件，需下载一个预编译的二进制安装器（<a class="reference external" href="https://mlocati.github.io/articles/gettext-iconv-windows.html">a precompiled binary installer</a>）。</p>
<p>你可能也想使用在其他地方获得的 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 二进制文件，只要 <code class="docutils literal notranslate"><span class="pre">xgettext</span> <span class="pre">--version</span></code> 命令工作正常即可。如果在命令行下输入 <code class="docutils literal notranslate"><span class="pre">xgettext</span> <span class="pre">--version</span></code> ，会导致报错：&quot;xgettext.exe 生成错误，并将被 Windows 关闭。&quot;，所以请不要试图使用带有 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 包的 Django 翻译工具。</p>
</div>
<div class="section" id="s-customizing-the-makemessages-command">
<span id="s-customizing-makemessages"></span><span id="customizing-the-makemessages-command"></span><span id="customizing-makemessages"></span><h3>自定义 <code class="docutils literal notranslate"><span class="pre">makemessages</span></code>&nbsp;命令<a class="headerlink" href="#customizing-the-makemessages-command" title="永久链接至标题">¶</a></h3>
<p>如果要给 <code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 传递额外的参数，则需要创建自定义的 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 命令，并覆盖它的 <code class="docutils literal notranslate"><span class="pre">xgettext_options</span></code> 属性：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.management.commands</span> <span class="kn">import</span> <span class="n">makemessages</span>

<span class="k">class</span> <span class="nc">Command</span><span class="p">(</span><span class="n">makemessages</span><span class="o">.</span><span class="n">Command</span><span class="p">):</span>
    <span class="n">xgettext_options</span> <span class="o">=</span> <span class="n">makemessages</span><span class="o">.</span><span class="n">Command</span><span class="o">.</span><span class="n">xgettext_options</span> <span class="o">+</span> <span class="p">[</span><span class="s1">&#39;--keyword=mytrans&#39;</span><span class="p">]</span>
</pre></div>
</div>
<p>如果需要更多的灵活性，也可以给自定义的 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">makemessages</span></code></a> 命令添加新的参数：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.management.commands</span> <span class="kn">import</span> <span class="n">makemessages</span>

<span class="k">class</span> <span class="nc">Command</span><span class="p">(</span><span class="n">makemessages</span><span class="o">.</span><span class="n">Command</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">add_arguments</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parser</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">add_arguments</span><span class="p">(</span><span class="n">parser</span><span class="p">)</span>
        <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
            <span class="s1">&#39;--extra-keyword&#39;</span><span class="p">,</span>
            <span class="n">dest</span><span class="o">=</span><span class="s1">&#39;xgettext_keywords&#39;</span><span class="p">,</span>
            <span class="n">action</span><span class="o">=</span><span class="s1">&#39;append&#39;</span><span class="p">,</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
        <span class="n">xgettext_keywords</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;xgettext_keywords&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">xgettext_keywords</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">xgettext_options</span> <span class="o">=</span> <span class="p">(</span>
                <span class="n">makemessages</span><span class="o">.</span><span class="n">Command</span><span class="o">.</span><span class="n">xgettext_options</span><span class="p">[:]</span> <span class="o">+</span>
                <span class="p">[</span><span class="s1">&#39;--keyword=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">kwd</span> <span class="k">for</span> <span class="n">kwd</span> <span class="ow">in</span> <span class="n">xgettext_keywords</span><span class="p">]</span>
            <span class="p">)</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">handle</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="s-miscellaneous">
<span id="miscellaneous"></span><h2>杂项<a class="headerlink" href="#miscellaneous" title="永久链接至标题">¶</a></h2>
<div class="section" id="s-the-set-language-redirect-view">
<span id="s-set-language-redirect-view"></span><span id="the-set-language-redirect-view"></span><span id="set-language-redirect-view"></span><h3><code class="docutils literal notranslate"><span class="pre">set_language</span></code> 重定向试图<a class="headerlink" href="#the-set-language-redirect-view" title="永久链接至标题">¶</a></h3>
<dl class="function">
<dt id="django.views.i18n.set_language">
<code class="descname">set_language</code>(<em>request</em>)<a class="headerlink" href="#django.views.i18n.set_language" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>方便起见，Django 附带了一个视图 <a class="reference internal" href="#django.views.i18n.set_language" title="django.views.i18n.set_language"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.views.i18n.set_language()</span></code></a> ，它可以设置用户语言首选项，并且重定向到一个给定的URL，或者默认情况下，会返回到上一页。</p>
<p>要激活这个视图，需要在你的 URLconf 中添加下面这行代码：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">path</span><span class="p">(</span><span class="s1">&#39;i18n/&#39;</span><span class="p">,</span> <span class="n">include</span><span class="p">(</span><span class="s1">&#39;django.conf.urls.i18n&#39;</span><span class="p">)),</span>
</pre></div>
</div>
<p>（注意这个例子会使视图在 <code class="docutils literal notranslate"><span class="pre">/i18n/setlang/</span></code> 下可用。）</p>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p class="last">确保在 <a class="reference internal" href="#django.conf.urls.i18n.i18n_patterns" title="django.conf.urls.i18n.i18n_patterns"><code class="xref py py-func docutils literal notranslate"><span class="pre">i18n_patterns()</span></code></a> 中不包含上述 URL —— 它需要独立于语言才能正常工作。</p>
</div>
<p>视图期望通过 <code class="docutils literal notranslate"><span class="pre">POST</span></code> 方法调用，并在请求中设置 <code class="docutils literal notranslate"><span class="pre">language</span></code> 参数。如果 session 支持是可用的，视图会在用户的 session 中保存语言选择。它也会将语言选择保存在默认名为 <code class="docutils literal notranslate"><span class="pre">django_language</span></code> （名称可以通过 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_NAME"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_NAME</span></code></a> 设置改变）的 cookie 中。</p>
<p>在设置语言选择后，Django 会检查 <code class="docutils literal notranslate"><span class="pre">POST</span></code> 或 <code class="docutils literal notranslate"><span class="pre">GET</span></code> 数据中的 <code class="docutils literal notranslate"><span class="pre">next</span></code> 参数。如果找到这个参数并且 Django 认为它是一个安全的链接（也就是说它不指向其他主机并使用安全模式），将会重定向到这个链接。否则，Django 可能会重定向到 <code class="docutils literal notranslate"><span class="pre">Referer</span></code> header 里的 URL，如果没设置这个 URL，则会跳转到 <code class="docutils literal notranslate"><span class="pre">/</span></code> ，这取决于请求的性质。</p>
<ul class="simple">
<li>如果请求接受 HTML 内容（基于其 <code class="docutils literal notranslate"><span class="pre">Accept</span></code> HTTP头），将始终执行回退。</li>
<li>如果请求不接受 HTML，只有在设置了 <code class="docutils literal notranslate"><span class="pre">next</span></code> 参数的情况下才会进行回退。否则将返回 204 状态码（无内容）。</li>
</ul>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p>在旧版本中，回退的区别是基于 <code class="docutils literal notranslate"><span class="pre">X-Requested-With</span></code> 头是否设置为 <code class="docutils literal notranslate"><span class="pre">XMLHttpRequest</span></code> 值。这是由 jQuery 的 <code class="docutils literal notranslate"><span class="pre">ajax()</span></code> 方法设置的。</p>
</div>
<p>这里是一个模板代码的例子：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">load</span> <span class="nv">i18n</span> <span class="cp">%}</span>

<span class="p">&lt;</span><span class="nt">form</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{%</span> <span class="k">url</span> <span class="s1">&#39;set_language&#39;</span> <span class="cp">%}</span><span class="s">&quot;</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">csrf_token</span> <span class="cp">%}</span>
    <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;next&quot;</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;hidden&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">redirect_to</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">select</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;language&quot;</span><span class="p">&gt;</span>
        <span class="cp">{%</span> <span class="k">get_current_language</span> <span class="k">as</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">%}</span>
        <span class="cp">{%</span> <span class="k">get_available_languages</span> <span class="k">as</span> <span class="nv">LANGUAGES</span> <span class="cp">%}</span>
        <span class="cp">{%</span> <span class="k">get_language_info_list</span> <span class="nv">for</span> <span class="nv">LANGUAGES</span> <span class="k">as</span> <span class="nv">languages</span> <span class="cp">%}</span>
        <span class="cp">{%</span> <span class="k">for</span> <span class="nv">language</span> <span class="k">in</span> <span class="nv">languages</span> <span class="cp">%}</span>
            <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">language.code</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="cp">{%</span> <span class="k">if</span> <span class="nv">language.code</span> <span class="o">==</span> <span class="nv">LANGUAGE_CODE</span> <span class="cp">%}</span> <span class="na">selected</span><span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span><span class="p">&gt;</span>
                <span class="cp">{{</span> <span class="nv">language.name_local</span> <span class="cp">}}</span> (<span class="cp">{{</span> <span class="nv">language.code</span> <span class="cp">}}</span>)
            <span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
        <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
    <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Go&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>在这个例子中，Django 会在 <code class="docutils literal notranslate"><span class="pre">redirect_to</span></code> 变量中查找用户将要重定向的网址。</p>
</div>
<div class="section" id="s-explicitly-setting-the-active-language">
<span id="s-id4"></span><span id="explicitly-setting-the-active-language"></span><span id="id4"></span><h3>显式设置语言<a class="headerlink" href="#explicitly-setting-the-active-language" title="永久链接至标题">¶</a></h3>
<p>你可能想显式地为当前会话设置语言。例如，可能是从另一个系统检索用户的语言偏好。你已经了解了 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.activate" title="django.utils.translation.activate"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.activate()</span></code></a> 。这只适用于当前进程。要将整个会话的语言保留在 cookie 中，请在响应上设置 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_NAME"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_NAME</span></code></a> ：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
<span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>
<span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">translation</span>
<span class="n">user_language</span> <span class="o">=</span> <span class="s1">&#39;fr&#39;</span>
<span class="n">translation</span><span class="o">.</span><span class="n">activate</span><span class="p">(</span><span class="n">user_language</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">LANGUAGE_COOKIE_NAME</span><span class="p">,</span> <span class="n">user_language</span><span class="p">)</span>
</pre></div>
</div>
<p>通常你想同时使用这两者：<a class="reference internal" href="../../ref/utils.html#django.utils.translation.activate" title="django.utils.translation.activate"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.activate()</span></code></a> 改变这个线程的语言，并设置cookie使此首选项在以后的请求中保持不变。</p>
</div>
<div class="section" id="s-using-translations-outside-views-and-templates">
<span id="using-translations-outside-views-and-templates"></span><h3>使用视图和模板外的翻译<a class="headerlink" href="#using-translations-outside-views-and-templates" title="永久链接至标题">¶</a></h3>
<p>虽然 Django 提供了一套丰富的i18n工具用于视图和模板，但它并不会限制 Django 特定代码的使用。Django 翻译机制可用于将任何文本翻译成 Django 支持的语言（当然，需要存在合适的翻译目录）。你可以加载翻译目录，激活它并翻译你选择的语言，但记住要切换回原始语言，因为激活语言目录是在每个线程基础上完成的，这样的改变将影响在同一线程中运行的代码。</p>
<p>例如:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">translation</span>

<span class="k">def</span> <span class="nf">welcome_translated</span><span class="p">(</span><span class="n">language</span><span class="p">):</span>
    <span class="n">cur_language</span> <span class="o">=</span> <span class="n">translation</span><span class="o">.</span><span class="n">get_language</span><span class="p">()</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">translation</span><span class="o">.</span><span class="n">activate</span><span class="p">(</span><span class="n">language</span><span class="p">)</span>
        <span class="n">text</span> <span class="o">=</span> <span class="n">translation</span><span class="o">.</span><span class="n">gettext</span><span class="p">(</span><span class="s1">&#39;welcome&#39;</span><span class="p">)</span>
    <span class="k">finally</span><span class="p">:</span>
        <span class="n">translation</span><span class="o">.</span><span class="n">activate</span><span class="p">(</span><span class="n">cur_language</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">text</span>
</pre></div>
</div>
<p>不论 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a>&nbsp; 和中间件设置的是什么，用 <code class="docutils literal notranslate"><span class="pre">'de'</span></code> 值调用的这个函数都会得到 <code class="docutils literal notranslate"><span class="pre">&quot;Willkommen&quot;</span></code> 。</p>
<p><a class="reference internal" href="../../ref/utils.html#django.utils.translation.get_language" title="django.utils.translation.get_language"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.get_language()</span></code></a> 会返回当前进程所使用的语言，<a class="reference internal" href="../../ref/utils.html#django.utils.translation.activate" title="django.utils.translation.activate"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.activate()</span></code></a> 会为当前进程激活翻译目录，<a class="reference internal" href="../../ref/utils.html#django.utils.translation.check_for_language" title="django.utils.translation.check_for_language"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.check_for_language()</span></code></a> 会检查 Django 是否支持给定的语言。</p>
<p>为了协助编写更简洁的代码，这里还有一个上下文管理器 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.override" title="django.utils.translation.override"><code class="xref py py-func docutils literal notranslate"><span class="pre">django.utils.translation.override()</span></code></a> ，它会在输入时存储当前语言，并在退出时恢复它。有了它，上面的例子可变为：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils</span> <span class="kn">import</span> <span class="n">translation</span>

<span class="k">def</span> <span class="nf">welcome_translated</span><span class="p">(</span><span class="n">language</span><span class="p">):</span>
    <span class="k">with</span> <span class="n">translation</span><span class="o">.</span><span class="n">override</span><span class="p">(</span><span class="n">language</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">translation</span><span class="o">.</span><span class="n">gettext</span><span class="p">(</span><span class="s1">&#39;welcome&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-language-cookie">
<span id="language-cookie"></span><h3>Language cookie<a class="headerlink" href="#language-cookie" title="永久链接至标题">¶</a></h3>
<p>可以使用一些设置来调整语言cookie选项：</p>
<ul class="simple">
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_NAME"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_NAME</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_AGE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_AGE</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_DOMAIN"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_DOMAIN</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_HTTPONLY"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_HTTPONLY</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_PATH"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_PATH</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_SAMESITE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_SAMESITE</span></code></a></li>
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_SECURE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_SECURE</span></code></a></li>
</ul>
</div>
</div>
<div class="section" id="s-implementation-notes">
<span id="implementation-notes"></span><h2>实施说明<a class="headerlink" href="#implementation-notes" title="永久链接至标题">¶</a></h2>
<div class="section" id="s-specialties-of-django-translation">
<span id="s-specialties-of-django-i18n"></span><span id="specialties-of-django-translation"></span><span id="specialties-of-django-i18n"></span><h3>Django 翻译的特性<a class="headerlink" href="#specialties-of-django-translation" title="永久链接至标题">¶</a></h3>
<p>Django 翻译机制使用 Python 自带的标准 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 模块。如果你知道  <code class="docutils literal notranslate"><span class="pre">gettext</span></code> ，你可能注意到了 Django 翻译的这些特性：</p>
<ul class="simple">
<li>字符串域为 <code class="docutils literal notranslate"><span class="pre">django</span></code> 或 <code class="docutils literal notranslate"><span class="pre">djangojs</span></code> 。这个字符串域用来区分在相同消息文件库(message-file library,通常为 <code class="docutils literal notranslate"><span class="pre">/usr/share/locale/</span></code> )中存有数据的不同项目。<code class="docutils literal notranslate"><span class="pre">django</span></code> 域被用于 Python和模板翻译字符串，以及加载到全局翻译目录。<code class="docutils literal notranslate"><span class="pre">djangojs</span></code> 域只用于 JavaScript 的翻译目录来确保它们尽可能小。</li>
<li>Django 不会单独使用 <code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 。它在 <code class="docutils literal notranslate"><span class="pre">xgettext</span></code> 和 <code class="docutils literal notranslate"><span class="pre">msgfmt</span></code> 周围使用 Python 装饰器。这主要是为了方便。</li>
</ul>
</div>
<div class="section" id="s-how-django-discovers-language-preference">
<span id="s-id5"></span><span id="how-django-discovers-language-preference"></span><span id="id5"></span><h3>Django 如何发现语言偏好<a class="headerlink" href="#how-django-discovers-language-preference" title="永久链接至标题">¶</a></h3>
<p>一旦你准备好了翻译——或者，如果你想使用Django自带的翻译——那么你需要激活你的项目的翻译。</p>
<p>在后台，Django 有一个非常灵活的模型来决定使用哪一种语言——在全局使用，还是特定用户使用，还是二者都有。</p>
<p>在全局范围内设置语言偏好，需要设置 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a> 。Django 使用这个语言作为默认翻译 —— 如果通过 locale 中间件所使用的方法之一没有找到匹配的翻译，那么这是最后的尝试（见下文）。</p>
<p>如果你指向用你的母语运行 Django ，那么你需要做的就是设置 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a> 并确保存在相应的消息文件及其编译版本 (<code class="docutils literal notranslate"><span class="pre">.mo</span></code>) 。</p>
<p>如果你想让每个独立用户指定他们想要的语言，则还需要使用 <code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 。<code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 可以基于请求中的数据启用语言选择。它为每个用户定制内容。</p>
<p>要使用 <code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code>，请在你的 <a class="reference internal" href="../../ref/settings.html#std:setting-MIDDLEWARE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">MIDDLEWARE</span></code></a> 配置中添加 <code class="docutils literal notranslate"><span class="pre">'django.middleware.locale.LocaleMiddleware'</span></code>。因为中间件的顺序很重要，所以要遵循这些准则。</p>
<ul class="simple">
<li>确保它是最先安装的中间件之一。</li>
<li>它应该在 <code class="docutils literal notranslate"><span class="pre">SessionMiddleware</span></code> 之后，因为 <code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 使用会话数据。而且它应该在 <code class="docutils literal notranslate"><span class="pre">CommonMiddleware</span></code> 之前，因为 <code class="docutils literal notranslate"><span class="pre">CommonMiddleware</span></code> 需要激活的语言来解析请求的 URL。</li>
<li>如果你使用 <code class="docutils literal notranslate"><span class="pre">CacheMiddleware</span></code>，把 <code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 放在它之后。</li>
</ul>
<p>例如，你的 <a class="reference internal" href="../../ref/settings.html#std:setting-MIDDLEWARE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">MIDDLEWARE</span></code></a> 可能看起来像这样：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">MIDDLEWARE</span> <span class="o">=</span> <span class="p">[</span>
   <span class="s1">&#39;django.contrib.sessions.middleware.SessionMiddleware&#39;</span><span class="p">,</span>
   <span class="s1">&#39;django.middleware.locale.LocaleMiddleware&#39;</span><span class="p">,</span>
   <span class="s1">&#39;django.middleware.common.CommonMiddleware&#39;</span><span class="p">,</span>
<span class="p">]</span>
</pre></div>
</div>
<p>（关于中间件的更多信息，请参见 <a class="reference internal" href="../http/middleware.html"><span class="doc">中间件文档</span></a>。）</p>
<p><code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 试图通过以下算法来确定用户的语言偏好。</p>
<ul>
<li><p class="first">首先，它在请求的URL中寻找语言前缀。 只有当你在你的根 URLconf 中使用 <code class="docutils literal notranslate"><span class="pre">i18n_patterns</span></code> 函数时，才会这样做。参见 <a class="reference internal" href="#url-internationalization"><span class="std std-ref">国际化：在 URL 模式中</span></a> 了解更多关于语言前缀和如何国际化 URL 模式的信息。</p>
</li>
<li><p class="first">如果失败，它将查找 cookie。</p>
<p>所使用的 cookie 的名称由 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_COOKIE_NAME"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_COOKIE_NAME</span></code></a> 设定。（默认名称是 <code class="docutils literal notranslate"><span class="pre">django_language</span></code>）。</p>
</li>
<li><p class="first">如果失败了，它将查看 <code class="docutils literal notranslate"><span class="pre">Accept-Language</span></code> HTTP 头。这个头由你的浏览器发送，并告诉服务器你喜欢哪种语言，按优先级排序。Django 会尝试每一种语言，直到找到可用的翻译。</p>
</li>
<li><p class="first">如果不行，则使用全局 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a> 设置。</p>
</li>
</ul>
<p id="locale-middleware-notes">注意：</p>
<ul>
<li><p class="first">在每一个地方，语言偏好都应该是标准的 <a class="reference internal" href="index.html#term-language-code"><span class="xref std std-term">语言格式</span></a>，作为一个字符串。例如，巴西葡萄牙语是 <code class="docutils literal notranslate"><span class="pre">pt-br</span></code>。</p>
</li>
<li><p class="first">如果基本语言可用，但指定的子语言不可用，Django 就使用基本语言。例如，如果用户指定了 <code class="docutils literal notranslate"><span class="pre">de-at</span></code> （奥地利德语），但 Django 只有 <code class="docutils literal notranslate"><span class="pre">de</span></code> 可用，Django 就使用 <code class="docutils literal notranslate"><span class="pre">de</span></code>。</p>
</li>
<li><p class="first">只有 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGES"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGES</span></code></a> 设置中列出的语言才能被选择。如果你想将语言选择限制在所提供的语言子集中（因为你的应用程序没有提供所有这些语言），请将 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGES"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGES</span></code></a> 设置为语言列表。例如：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">LANGUAGES</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="s1">&#39;de&#39;</span><span class="p">,</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;German&#39;</span><span class="p">)),</span>
    <span class="p">(</span><span class="s1">&#39;en&#39;</span><span class="p">,</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;English&#39;</span><span class="p">)),</span>
<span class="p">]</span>
</pre></div>
</div>
<p>这个例子将可供自动选择的语言限制为德语和英语（以及任何子语言，如 <code class="docutils literal notranslate"><span class="pre">de-ch</span></code> 或 <code class="docutils literal notranslate"><span class="pre">en-us</span></code>）。</p>
</li>
<li><p class="first">如果你定义了一个自定义的 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGES"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGES</span></code></a> 设置，就像上一弹所解释的那样，你可以将语言名称标记为翻译字符串——但要使用 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext_lazy" title="django.utils.translation.gettext_lazy"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext_lazy()</span></code></a> 而不是 <a class="reference internal" href="../../ref/utils.html#django.utils.translation.gettext" title="django.utils.translation.gettext"><code class="xref py py-func docutils literal notranslate"><span class="pre">gettext()</span></code></a> 来避免循环导入。</p>
<p>以下是一个实例配置文件:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="n">LANGUAGES</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="s1">&#39;de&#39;</span><span class="p">,</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;German&#39;</span><span class="p">)),</span>
    <span class="p">(</span><span class="s1">&#39;en&#39;</span><span class="p">,</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;English&#39;</span><span class="p">)),</span>
<span class="p">]</span>
</pre></div>
</div>
</li>
</ul>
<p>一旦 <code class="docutils literal notranslate"><span class="pre">LocaleMiddleware</span></code> 确定了用户的偏好，它就会将这个偏好作为 <code class="docutils literal notranslate"><span class="pre">request.LANGUAGE_CODE</span></code> 提供给每一个  <a class="reference internal" href="../../ref/request-response.html#django.http.HttpRequest" title="django.http.HttpRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">HttpRequest</span></code></a>。在你的视图代码中可以随意读取这个值。下面是一个例子：</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> <span class="n">HttpResponse</span>

<span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">LANGUAGE_CODE</span> <span class="o">==</span> <span class="s1">&#39;de-at&#39;</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="s2">&quot;You prefer to read Austrian German.&quot;</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">HttpResponse</span><span class="p">(</span><span class="s2">&quot;You prefer to read another language.&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>注意，静态（无中间件）翻译时，语言在 <code class="docutils literal notranslate"><span class="pre">settings.LANGUAGE_CODE</span></code> 中，而动态（中间件）翻译时，语言在 <code class="docutils literal notranslate"><span class="pre">request.LANGUAGE_CODE</span></code> 中。</p>
</div>
<div class="section" id="s-how-django-discovers-translations">
<span id="s-id6"></span><span id="how-django-discovers-translations"></span><span id="id6"></span><h3>Django 如何发现翻译<a class="headerlink" href="#how-django-discovers-translations" title="永久链接至标题">¶</a></h3>
<p>在运行时，Django 会在内存中建立一个统一的字面翻译目录。为了达到这个目的，它通过以下算法来查找翻译，关于它检查不同文件路径的顺序来加载编译的 <a class="reference internal" href="index.html#term-message-file"><span class="xref std std-term">消息文件</span></a> （<code class="docutils literal notranslate"><span class="pre">.mo</span></code>），以及同一字面意义的多个翻译的优先级。</p>
<ol class="arabic simple">
<li><a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a> 中列出的目录优先级最高，先出现的比后出现的优先级高。</li>
<li>然后，它会在 <a class="reference internal" href="../../ref/settings.html#std:setting-INSTALLED_APPS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">INSTALLED_APPS</span></code></a> 中列出的每个已安装的应用程序中寻找并使用是否存在 <code class="docutils literal notranslate"><span class="pre">locale</span></code> 目录。 先出现的比后出现的优先级高。</li>
<li>最后，在 <code class="docutils literal notranslate"><span class="pre">django/conf/locale</span></code> 中使用 Django 提供的基础翻译作为后备。</li>
</ol>
<div class="admonition seealso">
<p class="first admonition-title">参见</p>
<p>JavaScript 资产中包含的字词的翻译是按照类似但不相同的算法来查找的。更多细节请参见 <a class="reference internal" href="#django.views.i18n.JavaScriptCatalog" title="django.views.i18n.JavaScriptCatalog"><code class="xref py py-class docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code></a>。</p>
<p class="last">如果你还设置了 <a href="#id1"><span class="problematic" id="id2">:set:`FORMAT_MODULE_PATH`</span></a>，你也可以把 <a class="reference internal" href="formatting.html#custom-format-files"><span class="std std-ref">自定义格式文件</span></a> 放在 <a href="#id3"><span class="problematic" id="id4">:set:`LOCALE_PATHS`</span></a> 目录下。</p>
</div>
<p>在所有情况下，包含译文的目录名称应使用 <a class="reference internal" href="index.html#term-locale-name"><span class="xref std std-term">locale name</span></a> 符号来命名，如 <code class="docutils literal notranslate"><span class="pre">de</span></code>、<code class="docutils literal notranslate"><span class="pre">pt_BR</span></code>、<code class="docutils literal notranslate"><span class="pre">es_AR</span></code> 等。未翻译的地域语言变体字符串使用通用语言的翻译。例如，未翻译的 <code class="docutils literal notranslate"><span class="pre">pt_BR</span></code> 字符串使用 <code class="docutils literal notranslate"><span class="pre">pt</span></code> 翻译。</p>
<p>这样，你可以编写包含自己翻译的应用程序，你可以在你的项目中覆盖基础翻译。或者，你可以用几个应用程序构建一个大项目，并将所有翻译放到一个大的通用消息文件中，具体到你正在编写的项目。这是你的选择。</p>
<p>所有的消息文件库的结构都是一样的。它们是：</p>
<ul class="simple">
<li>配置文件的 <a class="reference internal" href="../../ref/settings.html#std:setting-LOCALE_PATHS"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LOCALE_PATHS</span></code></a> 中列出的所有路径都会被搜索到 <code class="docutils literal notranslate"><span class="pre">&lt;language&gt;/LC_MESSAGES/django.(po|mo)</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">$APPPATH/locale/&lt;language&gt;/LC_MESSAGES/django.(po|mo)</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">$PYTHONPATH/django/conf/locale/&lt;language&gt;/LC_MESSAGES/django.(po|mo)</span></code></li>
</ul>
<p>为了创建消息文件，你使用 <a class="reference internal" href="../../ref/django-admin.html#django-admin-makemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">makemessages</span></code></a> 工具。并使用 <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span></code></a> 来生成二进制的 <code class="docutils literal notranslate"><span class="pre">.mo</span></code> 文件，这些文件被 <code class="docutils literal notranslate"><span class="pre">gettext</span></code> 使用。</p>
<p>你也可以运行 <a class="reference internal" href="../../ref/django-admin.html#django-admin-compilemessages"><code class="xref std std-djadmin docutils literal notranslate"><span class="pre">django-admin</span> <span class="pre">compilemessages</span> <span class="pre">--settings=path.to.settings</span></code></a> 使编译器处理你 <a href="#id1"><span class="problematic" id="id2">:settings:`LOCALE_PATHS`</span></a> 设置中的所有目录。</p>
</div>
<div class="section" id="s-using-a-non-english-base-language">
<span id="using-a-non-english-base-language"></span><h3>使用非英语基础语言<a class="headerlink" href="#using-a-non-english-base-language" title="永久链接至标题">¶</a></h3>
<p>Django 一般假设可翻译项目中的原始字符串是用英语编写的。你可以选择其他语言，但你必须意识到某些限制。</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">gettext</span></code> 只为原始信息提供两种复数形式，所以如果基础语言的复数规则与英语不同，你还需要提供基础语言的翻译，以包括所有的复数形式。</li>
<li>当英文变体被激活而英文字符串缺失时，后备语言将不是项目的 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a>，而是原始字符串。例如，一个英语用户访问一个有 <a class="reference internal" href="../../ref/settings.html#std:setting-LANGUAGE_CODE"><code class="xref std std-setting docutils literal notranslate"><span class="pre">LANGUAGE_CODE</span></code></a> 设置为西班牙语的网站，而原来的字符串是用俄语写的，他看到的将是俄语文本而不是西班牙语。</li>
</ul>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">翻译</a><ul>
<li><a class="reference internal" href="#overview">概况</a></li>
<li><a class="reference internal" href="#internationalization-in-python-code">在 Python 代码中进行国际化</a><ul>
<li><a class="reference internal" href="#standard-translation">标准翻译</a></li>
<li><a class="reference internal" href="#comments-for-translators">为翻译者提供注释</a></li>
<li><a class="reference internal" href="#marking-strings-as-no-op">标记不用翻译的字符</a></li>
<li><a class="reference internal" href="#pluralization">多元化</a></li>
<li><a class="reference internal" href="#contextual-markers">上下文标记</a></li>
<li><a class="reference internal" href="#lazy-translation">惰性翻译</a><ul>
<li><a class="reference internal" href="#model-fields-and-relationships-verbose-name-and-help-text-option-values">模型字段和相关的 <code class="docutils literal notranslate"><span class="pre">verbose_name</span></code> 与 <code class="docutils literal notranslate"><span class="pre">help_text</span></code> 选项值</a></li>
<li><a class="reference internal" href="#model-verbose-names-values">模型详细名称的值</a></li>
<li><a class="reference internal" href="#model-methods-description-argument-to-the-display-decorator">Model methods <code class="docutils literal notranslate"><span class="pre">description</span></code> argument to the <code class="docutils literal notranslate"><span class="pre">&#64;display</span></code> decorator</a></li>
</ul>
</li>
<li><a class="reference internal" href="#working-with-lazy-translation-objects">使用惰性翻译对象</a><ul>
<li><a class="reference internal" href="#lazy-translations-and-plural">惰性翻译与复数</a></li>
<li><a class="reference internal" href="#formatting-strings-format-lazy">格式化字符串：<code class="docutils literal notranslate"><span class="pre">format_lazy()</span></code></a></li>
<li><a class="reference internal" href="#other-uses-of-lazy-in-delayed-translations">延迟翻译中惰性(lazy)的其他用法</a></li>
</ul>
</li>
<li><a class="reference internal" href="#localized-names-of-languages">语言的本地化名称</a></li>
</ul>
</li>
<li><a class="reference internal" href="#internationalization-in-template-code">在模板代码中国际化</a><ul>
<li><a class="reference internal" href="#translate-template-tag"><code class="docutils literal notranslate"><span class="pre">translate</span></code> 模板标签</a></li>
<li><a class="reference internal" href="#blocktranslate-template-tag"><code class="docutils literal notranslate"><span class="pre">blocktranslate</span></code> 模板标签</a></li>
<li><a class="reference internal" href="#string-literals-passed-to-tags-and-filters">传递字符串给标签和过滤器</a></li>
<li><a class="reference internal" href="#comments-for-translators-in-templates">模板内对翻译的注释</a></li>
<li><a class="reference internal" href="#switching-language-in-templates">在模板中选择语言</a></li>
<li><a class="reference internal" href="#other-tags">其他标签</a><ul>
<li><a class="reference internal" href="#get-available-languages"><code class="docutils literal notranslate"><span class="pre">get_available_languages</span></code></a></li>
<li><a class="reference internal" href="#get-current-language"><code class="docutils literal notranslate"><span class="pre">get_current_language</span></code></a></li>
<li><a class="reference internal" href="#get-current-language-bidi"><code class="docutils literal notranslate"><span class="pre">get_current_language_bidi</span></code></a></li>
<li><a class="reference internal" href="#i18n-context-processor"><code class="docutils literal notranslate"><span class="pre">i18n</span></code> 上下文处理器</a></li>
<li><a class="reference internal" href="#get-language-info"><code class="docutils literal notranslate"><span class="pre">get_language_info</span></code></a></li>
<li><a class="reference internal" href="#get-language-info-list"><code class="docutils literal notranslate"><span class="pre">get_language_info_list</span></code></a></li>
<li><a class="reference internal" href="#template-filters">模板过滤器</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#internationalization-in-javascript-code">国际化：在 JavaScript&nbsp;代码里</a><ul>
<li><a class="reference internal" href="#module-django.views.i18n"><code class="docutils literal notranslate"><span class="pre">JavaScriptCatalog</span></code> 视图</a></li>
<li><a class="reference internal" href="#using-the-javascript-translation-catalog">使用 JavaScript 翻译目录</a><ul>
<li><a class="reference internal" href="#gettext"><code class="docutils literal notranslate"><span class="pre">gettext</span></code></a></li>
<li><a class="reference internal" href="#ngettext"><code class="docutils literal notranslate"><span class="pre">ngettext</span></code></a></li>
<li><a class="reference internal" href="#interpolate"><code class="docutils literal notranslate"><span class="pre">interpolate</span></code></a></li>
<li><a class="reference internal" href="#get-format"><code class="docutils literal notranslate"><span class="pre">get_format</span></code></a></li>
<li><a class="reference internal" href="#gettext-noop"><code class="docutils literal notranslate"><span class="pre">gettext_noop</span></code></a></li>
<li><a class="reference internal" href="#pgettext"><code class="docutils literal notranslate"><span class="pre">pgettext</span></code></a></li>
<li><a class="reference internal" href="#npgettext"><code class="docutils literal notranslate"><span class="pre">npgettext</span></code></a></li>
<li><a class="reference internal" href="#pluralidx"><code class="docutils literal notranslate"><span class="pre">pluralidx</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-jsoncatalog-view"><code class="docutils literal notranslate"><span class="pre">JSONCatalog</span></code> 视图</a></li>
<li><a class="reference internal" href="#note-on-performance">性能说明</a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-django.conf.urls.i18n">国际化：在 URL 模式中</a><ul>
<li><a class="reference internal" href="#language-prefix-in-url-patterns">URL 模式中的语言前缀</a></li>
<li><a class="reference internal" href="#translating-url-patterns">翻译URL模式</a></li>
<li><a class="reference internal" href="#reversing-in-templates">在模板中反向解析URL</a></li>
</ul>
</li>
<li><a class="reference internal" href="#localization-how-to-create-language-files">本地化：如何创建语言文件</a><ul>
<li><a class="reference internal" href="#message-files">消息文件</a></li>
<li><a class="reference internal" href="#compiling-message-files">编译消息文件</a></li>
<li><a class="reference internal" href="#troubleshooting-gettext-incorrectly-detects-python-format-in-strings-with-percent-signs">疑难解答: <code class="docutils literal notranslate"><span class="pre">gettext()</span></code> 在带有百分号的字符串中错误地检测 <code class="docutils literal notranslate"><span class="pre">python-format</span></code></a></li>
<li><a class="reference internal" href="#creating-message-files-from-javascript-source-code">从 JavaScript 源码中创建消息文件</a></li>
<li><a class="reference internal" href="#gettext-on-windows">Windows 上的 <code class="docutils literal notranslate"><span class="pre">gettext</span></code></a></li>
<li><a class="reference internal" href="#customizing-the-makemessages-command">自定义 <code class="docutils literal notranslate"><span class="pre">makemessages</span></code>&nbsp;命令</a></li>
</ul>
</li>
<li><a class="reference internal" href="#miscellaneous">杂项</a><ul>
<li><a class="reference internal" href="#the-set-language-redirect-view"><code class="docutils literal notranslate"><span class="pre">set_language</span></code> 重定向试图</a></li>
<li><a class="reference internal" href="#explicitly-setting-the-active-language">显式设置语言</a></li>
<li><a class="reference internal" href="#using-translations-outside-views-and-templates">使用视图和模板外的翻译</a></li>
<li><a class="reference internal" href="#language-cookie">Language cookie</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation-notes">实施说明</a><ul>
<li><a class="reference internal" href="#specialties-of-django-translation">Django 翻译的特性</a></li>
<li><a class="reference internal" href="#how-django-discovers-language-preference">Django 如何发现语言偏好</a></li>
<li><a class="reference internal" href="#how-django-discovers-translations">Django 如何发现翻译</a></li>
<li><a class="reference internal" href="#using-a-non-english-base-language">使用非英语基础语言</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="index.html"
                        title="上一章">国际化和本地化</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="formatting.html"
                        title="下一章">本地格式化</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../../_sources/topics/i18n/translation.txt"
            rel="nofollow">显示源代码</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>快速搜索</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="转向" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">12月 07, 2021</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="index.html" title="国际化和本地化">previous</a>
     |
    <a href="../index.html" title="使用 Django" accesskey="U">up</a>
   |
    <a href="formatting.html" title="本地格式化">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>